// questions: // 1. why is the shape rotated slightly around the z-axis? // 2. why were the inside/outside scaling equations chosen? // 3. why do the first and last vertical lines connect to each other? #version 3.7; #include "Math.inc" global_settings { assumed_gamma 1 } camera { orthographic location <0, 0, -1> direction <0, 0, 1> up y scale 3/4 } light_source { <0, 0, -3000> color 1 parallel } plane { z, 0 texture { pigment { checker pigment { onion color_map { [000/100 color rgb 0/2] [001/100 color rgb 0/2] [001/100 color rgb 2/2] [099/100 color rgb 2/2] [099/100 color rgb 0/2] [100/100 color rgb 0/2] } scale 1/4 } pigment { onion color_map { [000/100 color rgb 2/2] [001/100 color rgb 2/2] [001/100 color rgb 0/2] [099/100 color rgb 0/2] [099/100 color rgb 2/2] [100/100 color rgb 2/2] } scale 1/4 } } } } #declare TWO_PI = 2 * pi; #declare iNx = 24; // the number of "horizontal" lines per charge, not taking into account iXmin #declare iNy = 32; // the number of "vertical" lines per charge #declare iXmin = 20; // size of the empty hole for each charge, measured in "horizontal" lines #declare iSym = 4; // number of charges arranged around the origin #declare iWidth = 300; // need to get rid of this #declare iHeight = 300; // need to get rid of this #declare iMouseX = 0; // need to get rid of this #declare iMouseY = 300; // need to get rid of this #declare bInside = true; // are the curved lines inside or outside of the reference shape? // or, are the charges inside or outside the reference shape? #declare bLines = true; // show lines connecting the points #macro mag(fX, fY) vlength() // return #end #macro dist(fX1, fY1, fX2, fY2) VDist(, ) //return #end #macro draw() #for (i, 0, iNy - 1) #local fY = i * TWO_PI/iNy; #for (j, iXmin, iNx - 1) #local fX1 = j * TWO_PI/iNx; #local fX2 = (j + 1) * TWO_PI/iNx; lines(fn(fX1, fY), fn(fX2, fY)) #end #end #for (i, iXmin, iNx) #local fX = i * TWO_PI/iNx; #for (j, 0, iNy - 1) #local fY1 = j * TWO_PI/iNy; #local fY2 = (j + 1) * TWO_PI/iNy; lines(fn(fX, fY1), fn(fX, fY2)) #end #end #end #macro lines(aP1, aP2) #for (i, 0, iSym - 1) #local fX1 = aP1[i][0]; #local fY1 = aP1[i][1]; #local fX2 = aP2[i][0]; #local fY2 = aP2[i][1]; sphere { , 0.005 pigment {color rgb x} } #if (bLines) cylinder { , , 0.005 pigment {color rgb x} } #end #end #end // this is where the magic happens ... #macro fn(fX, fY) #local aP = array[iSym][2]; #local fX1 = exp(fX) * cos(fY) + (iWidth/2 - iMouseX); #local fY1 = exp(fX) * sin(fY) + (iHeight/2 - iMouseY); #local fD = 0; #if (bInside = true) #local fD = 0.05 * pow(iSym, 1.5) * pow(mag(fX1, fY1), 1/iSym); // why this value? #else #local fD = 10 / log(iSym) * pow(mag(fX1, fY1), -1/iSym); // why this value? #end #local fArg = atan2(fX1, fY1) * -1/iSym; #for (i, 0, iSym - 1) #local fX2 = fD * cos(fArg + i * TWO_PI/iSym); #local fY2 = fD * sin(fArg + i * TWO_PI/iSym); #local aP[i][0] = fX2/TWO_PI; #local aP[i][1] = fY2/TWO_PI; #end aP //return #end draw()