Tiling by substitution

5

1

EDIT: The incorrect A rhomb substitution has been fixed. Apologies to anoyone who had started working on a solution.

Consider the following substitutions, where the substituted rhomb(us) is scaled up and shown in red:

EDIT: Note the anchor points (circle) created where a corner of each new rhomb touches the substituted rhomb. Also note the substitution's anchor point (black circle).

A rhomb (144°, 36°)

rhomb a ... becomes ... rhomb a subsitution 1

B rhomb (72°, 108°)

rhomb b ... becomes ... rhomb b substitution 1

Each substitution is made up of some combination of A rhombs and B rhombs, on which the same substitutions can be performed.

A tiling can be created by repeating the substitutions n times.

After n=2 substitutions of A rhomb:

EDIT: The substitution is oriented by aligning the rhomb's anchor point with the substitution's anchor point

rhomb a substitution 2

In the fewest bytes of code (given input n>=0) draw the tiling after n substitutions, where n=0 is A rhomb


Notes:

  • The red lines and anchor points shouldn't be included, they only illustrate the substitution.
  • In each substitution the tiling is scaled up so the rhombs have a constant size.
  • Any rotation is optional.
  • Graphical choices (colour, dimensions, cropping etc.) are optional if not exploited for loopholes.

jsh

Posted 2016-05-04T12:57:46.277

Reputation: 889

2Doesn't this require us to pay royalties to Roger Penrose? – Neil – 2016-05-04T13:16:48.280

very possibly, though as I understand it this isn't properly a Penrose tiling – jsh – 2016-05-04T13:26:48.793

3Please provide the exact angles and dimensions. – flawr – 2016-05-04T16:41:54.087

@flawr angles provided. each rhomb side is 1 unit, exact pixel dimensions are up to you – jsh – 2016-05-04T17:40:46.937

1The substitution for A does not match the n=2 example for the second level of substitution, no? In the substitution, two A rhombi are attached to a corner. In your example, one B rhombus is attached to a corner. – Marv – 2016-05-05T00:04:21.613

1Also it would be very helpful to know where the "origins" for the substitutions are, otherwise you're pretty much left playing the guessing game. My solution works for n=2 now, but I'm still getting wrongly rotated substitutions for n=3 – Marv – 2016-05-05T01:04:18.757

@Marv that's a mistake, I can't fix it yet but the substitution shown in n=2 is correct (one b rhomb attached to corner). sorry about this! – jsh – 2016-05-05T07:33:43.270

@Marv and regarding origins: when you perform a substitution each rhomb created has an anchor point where it touches a corner of the substituted rhomb. the next substitution is anchored to that point as seen in n=2. I'll make it clearer in an edit later – jsh – 2016-05-05T08:16:27.363

1@jsh Great edit, that clears things up. – Marv – 2016-05-05T12:01:50.990

1@jsh You should probably swap the angles for the B rhomb now since A is anchored at the first angle listed but B at the second. – Marv – 2016-05-05T12:06:52.463

Answers

3

Java, 881 bytes

import java.awt.image.BufferedImage;import static java.lang.Math.*;class J{BufferedImage o=new BufferedImage(999,999,1);java.awt.Graphics g=o.getGraphics();double v=2.5132,w=1.2566,p=PI,s=(p-v)/2,u=(p+w)/2;public static void main(String[]v){new J(Integer.parseInt(v[0]));}J(int i){d(609,391,v,p/4+s,500,i);try{javax.imageio.ImageIO.write(o,"png",new java.io.File("a.png"));}catch(Exception e){}}void d(int x,int y,double o,double q,double l,int r){int m=(int)(2*l*sin((p-o)/2)),a=(int)(x+cos(q)*l),b=(int)(y+sin(q)*l),c=(int)(x+cos(q+o/2)*m),d=(int)(y+sin(q+o/2)*m),e=(int)(x+cos(q+o)*l),f=(int)(y+sin(q+o)*l);if(r-->0){double n=l/(2*sin((v)/2));if(o>w){d(x,y,v,q-s,n,r);d(c,d,v,q+p+s,n,r);d(a,b,w,q+u,n,r);}else{d(x,y,w,q-s,n,r);d(c,d,w,q+p+s,n,r);d(e,f,w,q-p/2,n,r);d(a,b,v,q+p/2-s-s,n,r);}}else{g.drawLine(x,y,a,b);g.drawLine(a,b,c,d);g.drawLine(x,y,e,f);g.drawLine(c,d,e,f);}}}

Ungolfed

import java.awt.image.BufferedImage;

import static java.lang.Math.*;

class Q79373 {
    BufferedImage image = new BufferedImage(999, 999, 1);
    java.awt.Graphics graphics = image.getGraphics();
    double aRad = 2.5132, bRad = 1.2566, pi = PI, aAcuteHalf = (pi - aRad) / 2, bRadHalfPi = (pi + bRad) / 2;

    public static void main(String[] v) {
        new Q79373(Integer.parseInt(v[0]));
    }

    Q79373(int i) {
        draw(609, 391, aRad, pi / 4 + aAcuteHalf, 500, i);
        try {
            javax.imageio.ImageIO.write(image, "png", new java.io.File("a.png"));
        } catch (Exception e) {
        }
    }

    void draw(int x, int y, double rad, double rot, double length, int recDepth) {
        int
                height = (int) (2 * length * sin((pi - rad) / 2)),
                a = (int) (x + cos(rot) * length),
                b = (int) (y + sin(rot) * length),
                c = (int) (x + cos(rot + rad / 2) * height),
                d = (int) (y + sin(rot + rad / 2) * height),
                e = (int) (x + cos(rot + rad) * length),
                f = (int) (y + sin(rot + rad) * length);

        if (recDepth-- > 0) {
            double lengthNew = length / (2 * sin((aRad) / 2));
            if (rad > bRad) {
                draw(x, y, aRad, rot - aAcuteHalf, lengthNew, recDepth);
                draw(c, d, aRad, rot + pi + aAcuteHalf, lengthNew, recDepth);
                draw(a, b, bRad, rot + bRadHalfPi, lengthNew, recDepth);
            } else {
                draw(x, y, bRad, rot - aAcuteHalf, lengthNew, recDepth);
                draw(c, d, bRad, rot + pi + aAcuteHalf, lengthNew, recDepth);
                draw(e, f, bRad, rot - pi / 2, lengthNew, recDepth);
                draw(a, b, aRad, rot + pi / 2 - aAcuteHalf - aAcuteHalf, lengthNew, recDepth);
            }
        } else {
            graphics.drawLine(x, y, a, b);
            graphics.drawLine(a, b, c, d);
            graphics.drawLine(x, y, e, f);
            graphics.drawLine(c, d, e, f);
        }
    }
}

Notes

  • The results arent 100% acurate thanks to integer precision. I used integers for the coordinates because Graphics::drawLine only takes integers as arguments, and I would've ended up with way more integer casts than I have now.

  • I'll probably golf a bit more later, still not optimal.

Results

Full image filled

enter image description here

Recursion 1

enter image description here

Recursion 2

enter image description here

Recursion 3

enter image description here

Marv

Posted 2016-05-04T12:57:46.277

Reputation: 839

+1 but to fully meet the spec rhombs should have a constant size between recursions – jsh – 2016-05-05T13:29:38.767

1@jsh Oh gotcha, I'll change that later. – Marv – 2016-05-05T13:31:44.093

@jsh now I'm wondering if my solution is even correct. Penrose tilings on wikipedia have those neat stars all over, however I'm not getting those.

– Marv – 2016-05-05T17:14:11.913

this isn't a Penrose tiling though. I think your solution is correct – jsh – 2016-05-05T18:19:52.403