generating Poincare Discs

Lyle has found outside Gimp a place where to generate “Poincaré Disks”.
Is maybe possible to have that function as a G’MIC filter?
Lyle’s outcome can be seen here:
Online tool for generating Poincare Discs. • GIMP Chat

1 Like

Looking at the images, it seems that this could be easily doable if we know how to define the mapping ( u(x,y), v(,y) ) corresponding to this transformation.
No time to dive into the maths right now, so if you find the formula somewhere on the web, let me know, I’ll try implementing it.

Thanks David, I will ask Lyle who discovered and used this piece of external software and let you know.
Thanks again.

this is the site mentioned by Lyle in his post (in case this is what you look at)
site: Make Hyperbolic Tilings of Images

Saw your post at GIMPChat, Diego. No mathematically genius by any stretch, but maybe some hints can be found via a very old open source command line based poincare program I used in the past. :slight_smile:

Belows’s a link of some of the things created using this command line option. Biggest issue is define both location and creating the template used to create the results.

1 Like

Would love to see a G’MIC filter like this!

Lyle, I think your link is what I’m looking for.
(particularly the .pdf in section ‘Mathematics’ of the website : ).

I’m pretty sure this is something that could interest @garagecoder , @Reptorian and @grosgood as well (among others :slight_smile: ).

I’ll try to take the time to read this and see what I can do.
But I’ve got a lot of work waiting for me right now at the lab, so I’m not promising anything !

It does, but I’m on a refactor stage.

Of all the remarkable tessellations that Maurits Escher worked out over his lifetime, those projected on Poincaré Disks is, I think, his crowning achievement. Circle Limit III has captivated me since my early teens. Malin Christersson has certainly written comprehensive notes. I would think that the largely incomplete Math Expression series in Tutorial Land would provide a useful setting for an extended math expression example on how to play with homogeneous transformation matrices, which can encode in one matrix series of rotations and scalings; such a thing would operate at the heart of doing repetitive, patterned rotations and scalings that generates a Poincaré Disk.

Just don’t ask me when I might undertake this. Much depends on what moods strike me Sunday morning, just after breakfast.

1 Like

Seamless textures and definitely Tessellations, have intrigued me almost from the beginnings of my quest for creating computer artwork and Escher was one of my main inspirations. His Poincaré disk projections using objects just amazed me. Would really like an interactive interface for creating them and G’MIC would be that should someone take up that mantle (I’m just an end user; lol). Remember spending hours (no joke) figuring out how the commandline interface worked; not for the faint of heart. :slight_smile:

Until there’s a G’MIC preset, thought I would share a result from that site (and a few GIMP/G’MIC tricks in the mix). :slight_smile:

Two news.

  • The good news: I’ve managed to create this with G’MIC:


  • The bad news:

I’ve actually used a trick to do that, and I’ve not implemented the Poincaré disk at all.
I’ve just upload an identity map image to the website and get the resulting warp map that allowed me to generate this animation.
So, I cheated, and everything remains to be done (and it doesn’t look easy) :slight_smile: .


the bad news is the last sentence…hehehe

Looks cool, David, but you are a tease. lolololol

Hopefully the complex will end up with an easy solution. :slight_smile:

It’s likely to be more than a month before I can work on this. If it’s still an open task by then, the linked paper seems to describe it well enough for me to write a filter. Somehow I don’t think this one will still be waiting though :slight_smile:

Looking forward to this, GC; Bill was going to release a better version but he never did. Been a few years since I last revisited this topic, but then I ran across the online version that has a nice gui but doesn’t appear to do well with the seams. Still, gives nice results. Hope a G’MIC version would be much more interactive, but, again, I asketh for too mucheth. lol


OK, so I think I’m going in the right direction.
I’ve translated parts of the code from Bill Horne into the G’MIC language, and while I’m not able to deal with image data yet, at least I can generate the disk tiling and color each tile with its parity.

Maybe it can be a starting point for others ?



G’MIC Code : (clearly needs cleaning!!).

foo :

    # 'Circle.cpp': A Circle C is a vector [ x,y,r ].
    circle() = [ 0,0,1 ];

    circle(P,r) = [ P,r ];

    circle_inside_or_on(C,P) = (
      _dx = P[0] - C[0];
      _dy = P[1] - C[1];
      _dx^2 + _dy^2<=C[2]^2;

    circle_invert(C,P) = (
      _dx = P[0] - C[0];
      _dy = P[1] - C[1];
      _rSquared = _dx^2 + _dy^2;
      _r2 = C[2]^2/_rSquared;
      _x2 = _r2*_dx;
      _y2 = _r2*_dy;
      [ C[0] + _x2, C[1] + _y2 ];

    circle_create_edge_circle(p,q) = (
      _cosq2 = cos(pi/q)^2;
      _sinp2 = sin(pi/p)^2;
      _x = sqrt(_cosq2/(_cosq2 - _sinp2));
      _y = 0;
      _r = sqrt(_sinp2/(_cosq2 - _sinp2));
      [ _x,_y,_r ];

    # 'FundamentalRegion.cpp': A FundamentalRegion is a vector [ _edge.x,_edge.y,_edge.r,_m,_c,_s,_p ].
    fundamentalregion(p,q) = (
      _p = p;
      _edge = circle_create_edge_circle(p,q);
      _m = tan(pi/p);
      _c = cos(2*pi/p);
      _s = sin(2*pi/p);
      [ _edge,_m,_c,_s,_p ];

    fundamentalregion_inside(F,P) = (
      P[1]>F[3]*P[0] || P[1]<0 || circle_inside_or_on(F[0,3],P)?0:1

    fundamentalregion_reverse_pixel_lookup(F,A,max_iterations,OUT,parity) = (
      _ret = 0;
      _d = max_iterations;
      _B = A;
      while (_d>=0,
        _theta = atan2(_B[1],_B[0]);
        _r = sqrt(_B[0]^2 + _B[1]^2);
        while (_theta<0, _theta+=2*pi);
        while (_theta>pi/p, _theta-=2*pi/p);
        _C = [ _r*cos(_theta), _r*sin(_theta) ];
          parity# = !parity;
          OUT# = _C;
          _ret = 0;
        _B = circle_invert(F[0,3],_C);
        parity# = !parity;
          OUT# = _B;
          _ret = 0;
      _ret = 1;

    # 'main.cpp'
      const p = 6;
      const q = 4;

      (p - 2)*(q - 2)<4?run('error \"(p-2)(q-2) must be > 4 !\"');

      F = fundamentalregion(p,q);
      C = circle();

    x = lerp(-1.1,1.1,x/(w-1));
    y = lerp(-1.1,1.1,y/(h-1));

    P = [ x,y ];

    OUT = [ 0,0 ];
    parity = 1;


  r2dx 50% n 0,255

Cool stuff, David; definitely is a Poincare Disc. :slight_smile:

I don’t want to promise anything, but I’ve read the paper yesterday, and I think I got it, for the most parts. I’m almost sure I’ll be able to implement a pointcare disk filter in G’MIC one day or another :slight_smile:

Thanks a lot, David.