Logo by Madman - Contribute your own Logo!

END OF AN ERA, FRACTALFORUMS.COM IS CONTINUED ON FRACTALFORUMS.ORG

it was a great time but no longer maintainable by c.Kleinhuis contact him for any data retrieval,
thanks and see you perhaps in 10 years again

this forum will stay online for reference
News: Visit us on facebook
 
*
Welcome, Guest. Please login or register. January 19, 2018, 11:58:22 AM


Login with username, password and session length


The All New FractalForums is now in Public Beta Testing! Visit FractalForums.org and check it out!


Pages: [1] 2   Go Down
  Print  
Share this topic on DiggShare this topic on FacebookShare this topic on GoogleShare this topic on RedditShare this topic on StumbleUponShare this topic on Twitter
Author Topic: A new 3d mandelbrot-like fractal  (Read 6217 times)
0 Members and 1 Guest are viewing this topic.
Tglad
Fractal Molossus
**
Posts: 703


WWW
« on: December 10, 2009, 04:00:29 AM »

Hi everyone. Here are some pictures of a quite unique type of 3d mandelbrot.
They are based on an interesting property of the tetrahedron, that it can quadruple cover itself. It can fold into a tetrahedron with 1/4 the surface area.
So, just as the 2d mandelbrot folds a circle into itself and squares the distance circularly, this shape folds a tetrahedron into itself and squares the distance tetrahedrally.


* tetrahedralMandelbrot1.jpg (49.68 KB, 794x729 - viewed 562 times.)

* tetrahedralMandelbrot2.jpg (132.69 KB, 638x635 - viewed 575 times.)

* tetrahedralMandelbrot3.jpg (41.61 KB, 631x637 - viewed 563 times.)
Logged
David Makin
Global Moderator
Fractal Senior
******
Posts: 2286



Makin' Magic Fractals
WWW
« Reply #1 on: December 10, 2009, 01:46:42 PM »

That's cool !
OK, you have me interested - any chance on telling us the formula ?
Logged

The meaning and purpose of life is to give life purpose and meaning.

http://www.fractalgallery.co.uk/
"Makin' Magic Music" on Jango
kram1032
Fractal Senior
******
Posts: 1863


« Reply #2 on: December 10, 2009, 08:22:12 PM »

Niiice cheesy

The Mandeltenna or something smiley
Logged
Tglad
Fractal Molossus
**
Posts: 703


WWW
« Reply #3 on: December 11, 2009, 07:42:15 AM »

The description is simpler than my code, first you fold your point onto itself like the video
<a href="http://vimeo.com/moogaloop.swf?clip_id=8113730&amp;server=vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=01AAEA" target="_blank">http://vimeo.com/moogaloop.swf?clip_id=8113730&amp;server=vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=01AAEA</a>
Then if the distance was the radius of the tetrahedron that the point sat on, you square that radius... then add C.

I don't know a simple formula for the folding so the UF code manually maps triangles... so is more code than it should be. I'll try and simplify it down, before posting the code.
Do you know how to do multi-dimensional arrays in UF? I guess they're not possible, bummer.
Logged
lycium
Fractal Supremo
*****
Posts: 1158



WWW
« Reply #4 on: December 11, 2009, 07:49:49 AM »

Do you know how to do multi-dimensional arrays in UF? I guess they're not possible, bummer.

just do the additions and multiplications yourself; computer memory is 1d after all.
Logged

David Makin
Global Moderator
Fractal Senior
******
Posts: 2286



Makin' Magic Fractals
WWW
« Reply #5 on: December 11, 2009, 02:02:51 PM »

Do you know how to do multi-dimensional arrays in UF? I guess they're not possible, bummer.

just do the additions and multiplications yourself; computer memory is 1d after all.

Yes UF does do, for example:

  float myArray[5, 6, 10]
or
  float screenArray[#width+1, #height+1]

However it only does it with fixed-size arrays, not with the newer dynamic arrays which are one-dimensional only and the dimensions for the fixed-size arrays must be known at compile time.

Logged

The meaning and purpose of life is to give life purpose and meaning.

http://www.fractalgallery.co.uk/
"Makin' Magic Music" on Jango
Tglad
Fractal Molossus
**
Posts: 703


WWW
« Reply #6 on: December 12, 2009, 12:21:53 AM »

Thanks, here's the code:
Vector class:
Code:
class Vector(){
public:
  func Init(float xx, float yy, float zz)
    x = xx
    y = yy
    z = zz
  endfunc
  float func Dot(Vector other)
    return x*other.x + y*other.y + z*other.z
  endfunc
  func Divide(float f)
    x = x / f
    y = y / f
    z = z / f
  endfunc
  func Multiply(Vector a, float f)
    x = a.x * f
    y = a.y * f
    z = a.z * f
  endfunc
  func MultiplyEquals(float f)
    x = x * f
    y = y * f
    z = z * f
  endfunc
  func Normalise()
    float mag = sqrt(x*x + y * y + z*z)
    if mag>0
      x = x / mag
      y = y / mag
      z = z / mag
    endif
  endfunc
  float func Magnitude()
    return sqrt(x*x + y*y + z*z)
  endfunc
  func Add(Vector a, Vector b)
    x = a.x + b.x
    y = a.y + b.y
    z = a.z + b.z
  endfunc
  func AddEquals(Vector a)
    x = x + a.x
    y = y + a.y
    z = z + a.z
  endfunc
  func Subtract(Vector a, Vector b)
    x = a.x - b.x
    y = a.y - b.y
    z = a.z - b.z
  endfunc
  func Cross(Vector a, Vector b)
    float _x = (a.y * b.z) - (a.z * b.y)
    float _y = (a.z * b.x) - (a.x * b.z)
    float _z = (a.x * b.y) - (a.y * b.x)

    x = _x
    y = _y
    z = _z
  endfunc
  float x
  float y
  float z
}
Initialisation:
Code:
  Vector corners[4]  ; unit length tetrahedron corners
  corners[0] = new Vector()
  corners[1] = new Vector()
  corners[2] = new Vector()
  corners[3] = new Vector()
  corners[0].Init(0, 1, 0)
  corners[1].Init(0, -1/3, sqrt(8/9))
  corners[2].Init(-sqrt(2/3), -1/3, -(1/3) * sqrt(2))
  corners[3].Init(sqrt(2/3), -1/3, -(1/3) * sqrt(2))
  Vector normals[4]
  Vector crosses[4,3]  ; crosses[face index][corner index]. cross product of corners for inside-outside measures
  Vector C = new Vector()
  int triangles[4,3]  ; triangles[face index, corner of face]
  triangles[0, 0] = 0   ; wish I knew how to do an initialiser list
  triangles[0, 1] = 1
  triangles[0, 2] = 2
  triangles[1, 0] = 0
  triangles[1, 1] = 2
  triangles[1, 2] = 3
  triangles[2, 0] = 0
  triangles[2, 1] = 3
  triangles[2, 2] = 1
  triangles[3, 0] = 2
  triangles[3, 1] = 1
  triangles[3, 2] = 3
  ; for use later
  Vector point = new Vector()
  Vector corn0 = new Vector()
  Vector corn1 = new Vector()
  Vector corn2 = new Vector()
  Vector bary = new Vector()
  int it = 0
  repeat
    normals[it] = new Vector()
    crosses[it, 0] = new Vector()
    crosses[it, 1] = new Vector()
    crosses[it, 2] = new Vector()
    Vector cr1 = new Vector()
    cr1.Subtract(corners[triangles[it, 2]], corners[triangles[it, 0]])
    Vector cr2 = new Vector()
    cr2.Subtract(corners[triangles[it, 1]], corners[triangles[it, 0]])

    normals[it].Cross(cr1, cr2)
    normals[it].Normalise()
    ; leave this divide out below for an alternative where face of tetrahedron has magnitude 1, rather than corners. Produces slightly different shape
    normals[it].Divide(normals[it].Dot(corners[triangles[it, 0]]))  ; normal is not unit length so that a corner point gives dot of 1
    crosses[it, 0].Cross(corners[triangles[it, 2]], corners[triangles[it, 1]])
    crosses[it, 1].Cross(corners[triangles[it, 0]], corners[triangles[it, 2]])
    crosses[it, 2].Cross(corners[triangles[it, 1]], corners[triangles[it, 0]])
  until (it=it+1)>=4


  int squareMap[4,4,3]    ; squareMap[quadrant, face index, corner of quadrant]
  squareMap[0, 0, 0] = 0
  squareMap[0, 0, 1] = 1
  squareMap[0, 0, 2] = 2
  squareMap[0, 1, 0] = 0
  squareMap[0, 1, 1] = 2
  squareMap[0, 1, 2] = 3
  squareMap[0, 2, 0] = 0
  squareMap[0, 2, 1] = 3
  squareMap[0, 2, 2] = 1
  squareMap[0, 3, 0] = 0
  squareMap[0, 3, 1] = 3
  squareMap[0, 3, 2] = 1

  squareMap[1, 0, 0] = 1
  squareMap[1, 0, 1] = 0
  squareMap[1, 0, 2] = 3
  squareMap[1, 1, 0] = 2
  squareMap[1, 1, 1] = 0
  squareMap[1, 1, 2] = 1
  squareMap[1, 2, 0] = 3
  squareMap[1, 2, 1] = 0
  squareMap[1, 2, 2] = 2
  squareMap[1, 3, 0] = 3
  squareMap[1, 3, 1] = 0
  squareMap[1, 3, 2] = 2

  squareMap[2, 0, 0] = 2
  squareMap[2, 0, 1] = 3
  squareMap[2, 0, 2] = 0
  squareMap[2, 1, 0] = 3
  squareMap[2, 1, 1] = 1
  squareMap[2, 1, 2] = 0
  squareMap[2, 2, 0] = 1
  squareMap[2, 2, 1] = 2
  squareMap[2, 2, 2] = 0
  squareMap[2, 3, 0] = 1
  squareMap[2, 3, 1] = 2
  squareMap[2, 3, 2] = 0

  squareMap[3, 0, 0] = 1
  squareMap[3, 0, 1] = 3
  squareMap[3, 0, 2] = 2
  squareMap[3, 1, 0] = 2
  squareMap[3, 1, 1] = 1
  squareMap[3, 1, 2] = 3
  squareMap[3, 2, 0] = 3
  squareMap[3, 2, 1] = 2
  squareMap[3, 2, 2] = 1
  squareMap[3, 3, 0] = 3
  squareMap[3, 3, 1] = 2
  squareMap[3, 3, 2] = 1
Inner loop:
Code:
              ; convert c and z to vectors, for convenience
              C.x = real(cri)
              C.y = imag(cri)
              C.z = cj
              point.x = real(zri)
              point.y = imag(zri)
              point.z = zj
              float magnitude = 1
              int ij = 0  ; ij is just a unique name for the iterator over each tetrahedron face
              repeat
              magnitude = point.Dot(normals[ij])  ; normals isn't unit length so this gives radial magnitude in shape of tetrahedron
              if (magnitude > 0) ; on right side of triangle
                ; TDL super simple way to get barycentric coordinates of triangle
                bary.x = crosses[ij, 0].Dot(point)
                bary.y = crosses[ij, 1].Dot(point)
                bary.z = crosses[ij, 2].Dot(point)
              if (bary.x >= 0 && bary.y >= 0 && bary.z >= 0) ; correct face is found
                bary.Divide(bary.x+bary.y+bary.z)  ; barycentrics sum to 1
                int n = 0
                if (bary.x >= 0.5) ; quadrant 0
                  n = 0
                  bary.x = bary.x - 0.5
                elseif (bary.y >= 0.5) ; quadrant 1
                  n = 1
                  bary.y = bary.y - 0.5
                elseif (bary.x + bary.y <= 0.5) ; quadrant 2
                  n = 2
                else ; quadrant 3 (middle)
                  n = 3
                  float baryz = 1 - (bary.x + bary.y)
                  bary.y = 0.5 - bary.x
                  bary.x = 0.5 - baryz
                endif
                ; Z^2 + c
                bary.x = bary.x * 2  ; double the size here
                bary.y = bary.y * 2
                bary.z = 1 - (bary.x + bary.y)
                magnitude = magnitude*magnitude;
                corn0.Multiply(corners[squareMap[n, ij, 0]], bary.x)
                corn1.Multiply(corners[squareMap[n, ij, 1]], bary.y)
                corn2.Multiply(corners[squareMap[n, ij, 2]], bary.z)
                point.Add(corn0, corn1)
                point.AddEquals(corn2)
                point.MultiplyEquals(magnitude)
                point.AddEquals(C)
                ij=10 ; break out of loop since the face was found
              endif
              endif
              until (ij = ij+1)>=4
              zri = point.x + flip(point.y)      ; convert back to z
              zj = point.z


* tris.jpg (20.98 KB, 550x355 - viewed 466 times.)
Logged
David Makin
Global Moderator
Fractal Senior
******
Posts: 2286



Makin' Magic Fractals
WWW
« Reply #7 on: December 12, 2009, 12:58:54 AM »

Many thanks for posting that, I'll be having a play with it as soon as I've managed to streamline my current WIP formula.
Logged

The meaning and purpose of life is to give life purpose and meaning.

http://www.fractalgallery.co.uk/
"Makin' Magic Music" on Jango
Tglad
Fractal Molossus
**
Posts: 703


WWW
« Reply #8 on: December 12, 2009, 01:53:13 AM »

And lastly, if you make the following changes:
remove:     normals[it].Divide(normals[it].Dot(corners[triangles[it, 0]])) 
add:          magnitude = point.Magnitude()   after:     if (point.Dot(normals[ij]) > 0)
add:          point.Normalise()                      after:     point.AddEquals(corn2)
 
Then you get this alien overlord  smiley
It seems to be a valid inflation of the tetrahedron to a sphere. So it folds the sphere in a tetrahedron-like way.
Not conformal but the amount of stretch is bounded, so quasi-conformal I think.

 


* alien1.jpg (85.89 KB, 697x635 - viewed 438 times.)

* alien2.jpg (94.22 KB, 769x690 - viewed 469 times.)

* alienCloseUp.jpg (189.95 KB, 800x801 - viewed 415 times.)
Logged
kram1032
Fractal Senior
******
Posts: 1863


« Reply #9 on: December 13, 2009, 05:55:29 PM »

I wonder what happens with the smooth part on the bottom over time... smiley
Logged
Tglad
Fractal Molossus
**
Posts: 703


WWW
« Reply #10 on: December 15, 2009, 12:38:16 AM »

The alien fractal above is probably about 2-quasi conformal, which means a small sphere will map to an ellipse with long radius no more than twice the short radius.
In this measure it is better than the mandelbulb which is infinity-quasi conformal (unbounded stretch at the poles), but 2 is still quite stretched.
But the bigger issue with this fractal is that the mapping isn't smooth. It is continuous but not infinitely differentiable.
So an extension of this fractal is to make the mapping smoother (which will also make it more conformal). I don't know an analytic way, but here's a numeric way, just for the record:
- Take 1000 points spaced systematically on a unit sphere, record the lengths to their neighbours
- Map them all to the new sphere using the spherical tetrahedral mapping, double the recorded lengths
- Iteratively shift each point-pair to constrain the lengths to the recorded lengths
- Also constraint the points to remain on the unit sphere
This will generate a table-lookup mapping, that can be interpolated to generate a fast, smooth version of the alien fractal.
No idea if it would look better, but it would fill more criteria for a 3d mandelbrot.

Anyway, here's the power 3 version of the previous power 2 fractal


* alienPower3c.jpg (130.29 KB, 755x747 - viewed 416 times.)

* alienPower3b.jpg (63.57 KB, 546x472 - viewed 408 times.)

* alienPower3d.jpg (161.02 KB, 793x742 - viewed 415 times.)
Logged
Tglad
Fractal Molossus
**
Posts: 703


WWW
« Reply #11 on: January 13, 2010, 04:25:10 AM »

I implemented the routine described above, it iteratively changes the mapping towards a smoother and more conformal one. My my approximate measure, it takes the average eccentricity down from 1.9, to 1.5 where the 2d mandelbrot has eccentricity of 1. As you can see, the surface is a little rounder and there is almost no whipped-cream/taffy.

I then noticed that this was actually more like the tricorn of the 3d mandelbrot, and the base shouldn't be rotating 180 degrees. The unrotated shape in fascinating enough in itself that I'll post it in a separate topic.



* alienNew.jpg (110.86 KB, 782x695 - viewed 380 times.)

* alienNewClose.jpg (154.26 KB, 778x773 - viewed 372 times.)
Logged
David Makin
Global Moderator
Fractal Senior
******
Posts: 2286



Makin' Magic Fractals
WWW
« Reply #12 on: January 13, 2010, 12:46:02 PM »

Anyway, here's the power 3 version of the previous power 2 fractal

Can we see say the power 8 version of this one please ?
Logged

The meaning and purpose of life is to give life purpose and meaning.

http://www.fractalgallery.co.uk/
"Makin' Magic Music" on Jango
Tglad
Fractal Molossus
**
Posts: 703


WWW
« Reply #13 on: January 14, 2010, 02:01:30 AM »

Sure. The second one is power 8 from the tetrahedral mapping in my other post.
I don't see the point of using power 8 myself, it doesn't make the mapping less stretched overall


* alienPower8.jpg (160.17 KB, 756x720 - viewed 363 times.)

* tetrahedralMandelbulbPower8.jpg (155.43 KB, 753x711 - viewed 355 times.)
Logged
David Makin
Global Moderator
Fractal Senior
******
Posts: 2286



Makin' Magic Fractals
WWW
« Reply #14 on: January 14, 2010, 02:18:20 AM »

Sure. The second one is power 8 from the tetrahedral mapping in my other post.
I don't see the point of using power 8 myself, it doesn't make the mapping less stretched overall

I know but since most folks seem to find the power 8 Mandelbulb more aesthetically pleasing than the power 2 I wondered if the same would be true of the tetrahdral mapping version - I think the answer is probably yes but not by quite as great a margin smiley
Logged

The meaning and purpose of life is to give life purpose and meaning.

http://www.fractalgallery.co.uk/
"Makin' Magic Music" on Jango
Pages: [1] 2   Go Down
  Print  
 
Jump to:  


Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines

Valid XHTML 1.0! Valid CSS! Dilber MC Theme by HarzeM
Page created in 0.285 seconds with 28 queries. (Pretty URLs adds 0.019s, 2q)