File:Cactus model of Mandelbrot set.svg

From testwiki
Jump to navigation Jump to search

Original file(SVG file, nominally 534 × 448 pixels, file size: 55 KB)

This file is from Wikimedia Commons and may be used by other projects. The description on its file description page there is shown below.

Summary

Description
English: Topological model of Mandelbrot set (reflects the structure of the object). Topological model of Mandelbrot set without mini Mandelbrot sets and Misiurewicz points (Cactus model).
Polski: Topologiczny model zbioru Mandelbrota ( okazuje strukturę obiektu)
Date
Source Own work
Author Adam majewski
Other versions
SVG development
InfoField
 
The SVG code is valid.
 
This plot was created with Gnuplot.
This file supersedes the file Topological model of Mandelbrot set (reflects the structure of the object).png. It is recommended to use this file rather than the other one.

Bahasa Indonesia  davvisámegiella  Deutsch  English  español  français  italiano  magyar  Nederlands  polski  svenska  македонски  മലയാളം  português do Brasil  русский  slovenščina  日本語  中文(简体)  中文(繁體)  farsi  +/−

minor quality

Compare with

Explanation

It is topological model of Mandelbrot set without :

  • mini Mandelbrot sets
  • Misiurewicz points

Compare with :

  • "The Mandelbrot cactus" ("square" parametrisation) by Robert L. Devaney [1]
  • Lavaurs algorithm
  • model of basilica Julia set [2]

Algorithm

  • draw main circle ( analog to main cardioid of Mandelbrot set)
  • draw Ford circles on the main circle using
    • Farey sequences as an internal angle
    • new radius related with old radius and internal angle (p/q) :
GiveNewRadius(old,_p,_q):=old*abs(sin(%pi*_p/_q)/(_q*_q));[3]
  • repaet n-times the same procedure on each circle ( n is a number of steps)

Extension

One can do similar image but using cardioid as main component. [4]

Maxima CAS src code

First version

This version uses gnuplot svg terminal to make image.

Drawing code is dynamically created :

  • one instruction : plot2d (plots)
  • one list of parameters to display ( plots), which is created during computations


/* maxima cas batch script 
checked in 
Maxima version: 5.21.1
Maxima build date: 8:13 4/26/2010
Host type: i686-pc-mingw32
Lisp implementation type: GNU Common Lisp (GCL)
Lisp implementation version: GCL 2.6.8
*/



/* -----------------------------------definitions of functions -------------------------------------*/





/*  gives list o Farey fractions ( here internal angles in turns ) */
GiveFareySequence(n):=
block(
[a],
a:[0,1],
if n>=2 then
for denominator:2 thru n step 1 do
for numerator:1 thru (denominator-1) step 1 do
 a:cons(numerator/denominator,a),
  return(setify(a)) 
);

/* gives farey sequence without 0 and 1 angle */
GiveSequence(n):=
block(
[a],
a:GiveFareySequence(n),
/* remove 0 and 1 angle */
a:disjoin(0,a),
a:disjoin(1,a),
return(a)
);


GiveGlobalAngle(old,new):=mod(old-(1/2-new),1);


GiveNewRadius(old,_p,_q):=old*abs(sin(%pi*_p/_q)/(_q*_q));

/* 
distance = old_radius+new_radius ???
angle is global , it is measured in turns = rational number
*/
GiveNewCenter(old_c,distance,angle):=
realpart(old_c)+ distance*cos(2*%pi*angle)  + %i*(imagpart(old_c)+distance*sin(2*%pi*angle));



/* gives a list which is used by plot2d for drawing circle */
plot_circle(c,r):=[parametric, realpart(c)+r*cos(t), imagpart(c)+r*sin(t)];




plot_circles(_c,_r,old_global_angle,max_depth, max_denominator):=
block
(
[depth, /* order of components */
 angles,
 global_angle, /* angle in turns of line thru old and new center */
 plot_list,
 p,r,c],
depth:0,
plot_list:[],
plot_list:cons(plot_circle(_c,_r),plot_list),
/* main circle */
depth:depth+1,
if depth<max_depth
	then 
	(
	 angles:GiveSequence(max_denominator),
	 for local_angle in angles do
		(
		/* new internal angle = local angle */
		p:ratnum(local_angle),
		q:ratdenom(local_angle),
		global_angle:GiveGlobalAngle(old_global_angle,local_angle),
		/* new circle */
		r:GiveNewRadius(_r,p,q),
		c:GiveNewCenter(_c,_r+r,global_angle),
		plot_list:append(plot_circles(c,r,global_angle,max_depth-1,max_denominator),plot_list))
	 
	),
return(plot_list)
);










/* ------------------------------------initial values ------------------------------*/

radius:1;
center:0;
denominator:7; /* max denominator of internal angle; then 2*denominator circles are drawn at each level of depth */
MainAngle:1/2;
MaxDepth:4;  /* den = 10 and depth= 4  gives an error */
plots:[]; /* list for plot2d */
file_title:concat("circle_",string(denominator),"_",string(MaxDepth),".svg");


/* ---------------------  computing -----------------------------------------*/

plots:plot_circles(center,radius,MainAngle,MaxDepth, denominator);


/* --------------------------- drawing code ---------------------------------------*/

set_plot_option([plot_format, gnuplot]);
set_plot_option([nticks, 80]);
set_plot_option([t,-%pi,%pi]); 
set_plot_option([gnuplot_preamble, "unset key;set title 'Topological model of Mandelbrot set'"])$ /* */
set_plot_option([color,black]);
set_plot_option([gnuplot_term, svg]);
set_plot_option([gnuplot_out_file, file_title]);

plot2d (plots)$ /* plots uses list 'plots' . Dynamically generating the plot commands */

Comments :

  • plots list created by this program grows rapidly and makes memory problems
  • svg file contains paths not circles. Why ?

Second version

SVG file is directly created thru concatenate of strings.

There are also some changes in svg code :

/* maxima cas batch script 

checked in 

Maxima version: 5.21.1

Maxima build date: 8:13 4/26/2010

Host type: i686-pc-mingw32

Lisp implementation type: GNU Common Lisp (GCL)

Lisp implementation version: GCL 2.6.8



https://commons.wikimedia.org/wiki/File:Circle_7_4.svg

*/





kill(all);
remvalue(all);

/* -----------------------------------definitions of functions -------------------------------------*/











/*  gives list o Farey fractions ( here internal angles in turns ) */

GiveFareySequence(n):=

block(

[a],

a:[0,1],

if n>=2 then

for denominator:2 thru n step 1 do

for numerator:1 thru (denominator-1) step 1 do

 a:cons(numerator/denominator,a),

  return(setify(a)) 

);



/* gives farey sequence without 0 and 1 angle */

GiveSequence(n):=

block(

[a],

a:GiveFareySequence(n),

/* remove 0 and 1 angle */

a:disjoin(0,a),

a:disjoin(1,a),

return(a)

);







/* -  circle functions --------------*/

GiveGlobalAngle(old,new):=mod(old-(1/2-new),1);





GiveNewRadius(old,_p,_q):=1.2*float(old*abs(sin(%pi*_p/_q)/(_q*_q)));



/* 

distance = old_radius+new_radius 

angle is global , it is measured in turns = rational number

*/

GiveNewCenter(old_c,distance,angle):=float(

realpart(old_c)+ distance*cos(2*%pi*angle)  + %i*(imagpart(old_c)+distance*sin(2*%pi*angle)));













/* uses global var angles */

plot_circles(dest,_c,_r,old_global_angle,max_depth):=

block

(

[depth, /* order of components */

 

 global_angle, /* angle in turns of line thru old and new center */

  p,r,c],

depth:0,

c:_c,

r:_r,



/* parent circle */

if (r> minimal_radius) 

	then CircleSVG(dest,realpart(_c),imagpart(_c),r),

	

depth:depth+1,

if depth<max_depth

	then 

	 for local_angle in angles do

		(

		/* new internal angle = local angle  gives childrens*/

		p:ratnum(local_angle),

		q:ratdenom(local_angle),

		global_angle:GiveGlobalAngle(old_global_angle,local_angle),

		/* new circle */

		r:GiveNewRadius(_r,p,q),

		c:GiveNewCenter(_c,_r+r,global_angle),

		if (r> minimal_radius) 

	then plot_circles(dest,c,r,global_angle,max_depth-1))

	 

	

);



/* ---------------------------------basic svg functions -----------------------*/



BeginSVG(file_name,cm_width,cm_height,i_width,i_height,_strokeWidth):=

block(

	destination : openw (file_name),

	printf(destination, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>~%"),

	printf(destination, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"~%\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">~%"),



	printf(destination,"<svg width=\"~dcm\" height=\"~dcm\" viewBox=\"0 0 ~d ~d\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">~%", /* no space between number and unit */

	cm_width,cm_height,i_width,i_height),
	printf(destination,"<g fill=\"white\" stroke=\"black\" stroke-width=\"~f\">",_strokeWidth), /* all shapes in group have the same width and color */

	return(destination)

);





CircleSVG(dest,center_x,center_y,_radius):=

printf(dest,"<circle cx=\"~f\" cy=\"~f\" r=\"~f\" />~%",

	center_x,center_y,_radius);

	

	

EndSVG(destination):=

(
printf(destination,"</g>~%"), /* close the group */

printf(destination,"</svg>~%"),

close (destination)

);










compile(all);


/* ------------------------------------initial values ------------------------------*/



stroke_width:0.5; /* width of circle boundary */

minimal_radius:stroke_width; /* radius of minimal circle to draw */

iWidth:1600; 

iHeight:1200; 

radius:iHeight/4; 

center:(iWidth - iWidth/4)  + %i*iHeight/2; /* in pixels */

max_denominator:15; /* max denominator of internal angle; then 2*denominator circles are drawn at each level of depth */

MainAngle:1/2;

MaxDepth:6;  /* depth greater then 5 is to big cause radii are small */

numberOfCircles:1+max_denominator^MaxDepth;



/* --------------- svg file --------------------------  */

path:"~/maxima/batch/mandel/shrub/"$ /* pwd  ; if you put here working directory name then graphic file will be saved in that dir */

file_title:concat(path, "c_",string(max_denominator),"_",string(MaxDepth),"_",string(minimal_radius),".svg");





/* ---------------------  computing and making svg file -----------------------------------------*/

angles:GiveSequence(max_denominator); /* global var */

f:BeginSVG(file_title,60,40,iWidth,iHeight,stroke_width);

plot_circles(f, center,radius, MainAngle, MaxDepth);

_time:time(%);

EndSVG(f);





/* ------------------------info -------------------------------------------------------------- ----- */

disp(concat("file  ",file_title, " made of ",string(numberOfCircles)," circles in ",string(_time[1]),"  sec"));







C src code

SVG development

InfoField
 
The SVG code is valid.
 
This vector image was created with a text editor.

Source code

InfoField

C src code

/*

gcc d.c -Wall -lm


angle is measured :
* in turns 
* counterclockwise 

https://en.wikipedia.org/wiki/Turn_(geometry)

angle can be :
* global ( 0 = 1 is on horizontal = x axis )
* local, where 0 is internal angle of parent 

compare with : 
[[:File:Circle 7 4.svg|Circle 7 4.svg]]


mutually and externally tangent circles
http://mathworld.wolfram.com/TangentCircles.html
Two circles are mutually and externally tangent if distance between their centers is equal to the sum of their radii

check
https://validator.w3.org/check

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h> //strncat
#include <math.h> // sin, M_PI




/* -  ------ global variables ---------- */
 
          
           
// RGB colors
 // http://www.december.com/html/spec/color4.html  
char *black    = "#000"; /* hexadecimal number as a string for svg color*/
char *white    = "#FFF";
char *burgundy = "#9E0508";
char *SeaGreen = "#068481";
char *turquoise= "#40E0D0";
char *red      = "#F00";
char *navy     = "#000080";
char *blue     = "#00F";

	 	 
 // svg file 
 FILE * fp;
 char *filename; //="shrub.svg";
 // svg parameters 
 char *comment = "";
 double stroke_width = 0.5;
 double minimal_radius; /* radius of minimal circle to draw */

 char *stroke_color ; 
 char *fill_color ;
 
 double  Xmax = 1000.0;
 double  Ymax = 1000.0;
 
 
 
 
 // main circle = period 1 
  double  r1; // radius
 // center = x1 + y1*I;
 double X1;
 double Y1;
 
 
 const int iLevelMax = 4; // 
 const int dMax = 14;  // maximal denominator of internal angle 
 const double main_angle = 0.5; // in turns
 
// ----------------- functions -------------------------------

double  min(double a, double b) {
  return a < b ? a : b;
}



void beginSVG(void){


  char name [30]; /* name of file */
  snprintf(name,20,"%d_%d",dMax, iLevelMax ); /*  */
  filename =strncat(name,".svg", 24);



 fp = fopen( filename,"w");
 if( fp == NULL ) {printf (" file open error \n"); return ; }
 stroke_color = black; // stroke
 fill_color = white; // fill
 minimal_radius = stroke_width; /* radius of minimal circle to draw */
 
 // period 1 circle
 // center 
 X1 = Xmax - Xmax/3.0;
 Y1 = Ymax/2.0;
 r1 = min(X1, Y1)- 2.0*min(X1, Y1)/3.0; // radius
 


 fprintf(fp,
     "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
     "%s \n "
     "<svg width=\"20cm\" height=\"20cm\" viewBox=\"0 0 %.0f %.0f\"\n"
     " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n",
     comment,Xmax,Ymax);

  fprintf(fp,"<g stroke=\"%s\" stroke-width=\"%f\" fill=\"%s\">\n",   stroke_color, stroke_width, fill_color); // group open

printf(" beginSVG done \n");

}




void EndSVG(void){
 fprintf(fp,"</g>\n"); // group close
 fprintf(fp,"</svg>\n"); // svg close
 fclose(fp); // file close 
 printf("endSVG done\n file %s saved \n",filename );
}



// draw circle to svg file
void draw_circle(double x, double y,  double radius ){

    
       fprintf(fp,"<circle cx=\"%.1f\" cy=\"%.1f\" r=\"%.1f\" />\n", x, y, radius);
      // else printf ("radius < minimal_radius\n");
}





  
/*
https://stackoverflow.com/questions/19738919/gcd-function-for-c
The GCD function uses Euclid's Algorithm. 
It computes A mod B, then swaps A and B with an XOR swap.
*/

int gcd(int a, int b)
{
    int temp;
    while (b != 0)
    {
        temp = a % b;

        a = b;
        b = temp;
    }
    return a;
}



// GiveNewRadius(old,_p,_q):=old*abs(sin(%pi*_p/_q)/(_q*_q))

double GiveNewRadius(double OldRadius, int num, int den ){

  //double t = (double)num / den;
  double d2 = den*den;
  //printf( "t = %f ;  d2 = %f ",t, d2);
  //double temp =(num*num)/d2;
  //printf( "temp = %f ; ",temp);
  return 1.3*OldRadius/d2; //
}


//GiveGlobalAngle(old,new):=mod(old-(1/2-new),1);
double GiveNewAngle (double old, double n, double d) {
  double t =old-(main_angle-n/d);
  if (t > 1.0) t-=1.0;
  return t;
}





/*
    test_v =Test(x1,y1, r1, x,y, Radius);
    printf(" n/d = %d / %d \n", num, den );
    printf( "main circle center = (%f ; %f) radius = %f \n", x1,y1, r1);
    printf( "new  circle center = (%f ; %f) radius = %f \n", x,y, Radius);
    printf( "test = %f \n", test_v);
    */
long double Test(double x1, double y1, double r1, double x2, double y2, double r2){

return (sqrt((x1-x2)*(x1-x2)+ (y1-y2)*(y1-y2)) - (r1+r2));

}




// shrub is a part of the limb after Myrberg-Feigenbaum point ( end of period doubling cascade )
void DrawShrub(double n, double d){

}

/*

. The part of the Mandelbrot set connected to the main cardioid at this bifurcation point is called the p/q-limb. 
*/




// t = global angle in turns
void drawSVG(double t,  int iLevel, double x, double y, double r)
{
 // internal angle = n/d 
 int n;  // numerator
 int d;  // denominator
 
 
 double r_new; // Radius;
 double x_new,y_new; // center
 double distance; // new_radius + old_radius
 double t_local;
 int iLevel_new;

    
 
 
 
  draw_circle(x,y,r); 
 
 
 
   for (d = 2; d <= dMax; ++ d ){
     
     for (n = 1; n < d; ++ n ){
       if (gcd(n,d)==1 )// irreducible fraction
            {
            
           if ( iLevel > iLevelMax) { 
               DrawShrub(n,d);
               break;}
           iLevel_new = iLevel +1;
           
           // num/den * 1/2  where 1/2 is a local angle 
           // period doubling cascade 
           // new radius
           r_new = GiveNewRadius(r, n, d );
           if (r_new > minimal_radius) {
           //
           distance =  r + r_new  ;
           //printf("n = %d; d = %d iRadius = %d \n", num, den, iRadius);
           // new center
           t_local = GiveNewAngle(t, n, d);
           x_new = x + distance* cos(2.0*M_PI*t_local);
           y_new = y + distance* sin(2.0*M_PI*t_local);
           //
           drawSVG(t_local, iLevel_new, x_new, y_new, r_new);  
           }
           
           
           
           } //  if(gcd
     } // for (n
   } // for(d 
   
   
  
  
  
}


// ------------------------------------- main ---------------------------------------------------
int main(){
    
 

 
 
 
 
   
 beginSVG();  
 
 drawSVG(main_angle, 0, X1, Y1, r1);  
 
       
 EndSVG();
 
 
 return 0;
}

References

  1. The Mandelbrot cactus by Robert L. Devaney
  2. Combinatorial Julia Sets (1) By Jim Belk
  3. Mu Atom Sizes by Robert Munafo
  4. From Farey sequence to M-set: archive copy at the Wayback Machine

Licensing

I, the copyright holder of this work, hereby publish it under the following licenses:
w:en:Creative Commons
attribution share alike
This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license.
You are free:
  • to share – to copy, distribute and transmit the work
  • to remix – to adapt the work
Under the following conditions:
  • attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
  • share alike – If you remix, transform, or build upon the material, you must distribute your contributions under the same or compatible license as the original.
GNU head Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License.
You may select the license of your choice.

Captions

Add a one-line explanation of what this file represents

Items portrayed in this file

depicts

20 June 2010

image/svg+xml

93368ab03162d5aad29dcb18eee26a5684c7cbe8

56,275 byte

448 pixel

534 pixel

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeThumbnailDimensionsUserComment
current12:42, 28 July 2018Thumbnail for version as of 12:42, 28 July 2018534 × 448 (55 KB)wikimediacommons>Trlkly"Cropped" out empty space, and further optimized (with Inkscape) without losing any precision.

The following page uses this file: