Levy C Curve

​The Levy C Curve looks like this:

To generate it, you start with a line segment. This is the first stage. Then you replace the line segment with Two line segments, such that they form an isosceles triangle with the initial line, where the initial line is the hypotenuse. For stage three, you replace each of the two lines from stage two with two lines, again forming isosceles triangles with the stage two lines as the hypotenuses. You continue this pattern iteratively, and the form you create is termed the Levy C curve, named 'C' for the letter it resembles. 

(preceding picture courtesy of wikipedia)

Here's a video showing the evolution of the Levy C curve through the first few stages. 

Here's the code used to generate the figure:

function LevyC_Curve(iterations,angle)
% Draws a Levy C Curve for the given number of iterations

    pts=[0,0;1,0];
    length=1; % length of the hypotenuse
    
    % Initialize the figure and draw the first stage (a line)
    figure('Position',[50,50,1000,750],'Color',[1 1 1]);
    c=[0 0 1];
    plot([0 1],[0 0],'Color',c,'LineWidth',1)
    hold on
    xlim([-0.5,1.5]);
    ylim([-1,0.5]);
    axis off
    
    % Repeat for the given number of iterations
    for i=1:iterations
        
        % Clear the current figure
        cla 
        % Calculate the length of the new line segments
        length=0.5*length/cosd(angle);
        % This will store all the points of the Levy C curve
        temp=[]; 
        
        % For each line segment, do the following
        for j=1:size(pts,1)-1 
            
            % Grab the endpoints of the current line segment. 
            pt1=pts(j,:);
            pt2=pts(j+1,:);
            
            % Subtract one endpoint from the other, so you're dealing with
            % rotations about the origin.
            pt2corr=pt2-pt1;
            
            % These lines determine the angle theta, which is calculated
            % slightly differently depending on which quadrant you end up
            % in.
            if 0>=pt2corr(1) && 0>=pt2corr(2)
                theta=atand(abs(pt2corr(2)/pt2corr(1)))+180;
            elseif 0>=pt2corr(1)
                theta=180-atand(abs(pt2corr(2)/pt2corr(1)));
            elseif 0>=pt2corr(2)
                theta=360-atand(abs(pt2corr(2)/pt2corr(1)));
            else
                theta=atand(abs(pt2corr(2)/pt2corr(1)));
            end
            
            % Calculate the 'midpoint' ; the vertex of the triangle
            midpt=[length*cosd(theta-angle)+pt1(1),length*sind(theta-angle)+pt1(2)];
            c=[j/size(pts,1) 0 1-j/size(pts,1)];
            
            % Plot the current lines
            plot([pt1(1),midpt(1),pt2(1)],[pt1(2),midpt(2),pt2(2)],'Color',c,'LineWidth',1)
            hold on
            xlim([-0.5,1.5]);
            ylim([-1,0.5]);
            axis off
            
            % Add the first endpoint and midpoint to the list of points
            temp=[temp;pt1;midpt]; 
            
        end
        
        % Append the final point to the list of points
        temp=[temp;pts(end,:)]; 
        % Briefly pause to view the current iteration
        pause(1)  
        % Store the previous iteration's points in the pts variable
        pts=temp; 
    end
end

Adding some variation:

The Levy C curve can be tiled in some very interesting ways.

Triangular Form:

What if instead of starting with a line, we started with a triangle? 

Triangular Form (inwards):

What if, instead of the iteration going outwards from the triangle, they went inwards?

Square form:

What if we started with a square?

Square form (separated): 

What if we started with a square, but separated out the sides?

Square Form (inwards): 

What if we started with a square, but had the angles propagate inwards? This is a common form of the Levy C curve, and is commonly called a carpet. 

Code

All of these (except the separated square one) can be made using the following Matlab function:

function LevyC_Curve_General(iterations,angle,inverted,makeVideo,shape)
% Generates a Levy C curve that startes from a triangle, with inputs:
%   iterations = int; total number of iterations
%   angle = number; angle at which the Levy C curve is computed
%   inverted = 1 or 0; set to 1 to invert the angles (so they go inward)
%   makeVideo = 1 or 0; set to 1 to make a video
%   shape = 1, 2, or 3; 1 = line; 2 = triangle; 3 = square

    % If making a video, set up the video object
    if makeVideo==1
        writerObj = VideoWriter('levyC_squareVideoNew1'); % Name it.
        writerObj.FrameRate = 1;
        writerObj.Quality=100;
        open(writerObj)
    end

    length=1;
    
    % Initialize the figure
    figure('Position',[50,50,700, 700],'Color',[1 1 1]);
    c=[0 0 1];
    
    % Set the initial points for whichever shape you are drawing and plot
    % them. Also set the x and y limits for the graph. 
    
    % Starting with a LINE
    if shape==1
        pts=[0,0;1,0];
        plot([0 1],[0 0],'Color',c,'LineWidth',1)
        xlimValues=[-.5,1.5];
        ylimValues=[-1,0.5];        
        
    % Starting with a TRIANGLE
    elseif shape==2
        pt3=[cosd(120) -sind(120); sind(120) cosd(120)]*[1;0]+[0.5;0];
        pts=[-0.5,0;0.5,0;pt3'];
        plot([pts(1,1) pts(2,1) pts(3,1) pts(1,1)],[pts(1,2) pts(2,2) pts(3,2) pts(1,2)],'Color',c,'LineWidth',1)
        if inverted==1
            xlimValues=[-1,1];
            ylimValues=[-.75,1.25];
        else
            xlimValues=[-1.5,1.5];
            ylimValues=[-1.25,2.25];            
        end
        
    % Starting with a SQUARE    
    elseif shape==3
        pts=[-0.5,-0.5;0.5,-0.5;0.5,0.5;-0.5,0.5];
        plot([pts(1,1) pts(2,1) pts(3,1) pts(4,1) pts(1,1)],[pts(1,2) pts(2,2) pts(3,2) pts(4,2) pts(1,2)],'Color',c,'LineWidth',1)
        if inverted==1
            xlimValues=[-1.5,1.5];
            ylimValues=[-1.5,1.5];           
        else
            xlimValues=[-2,2];
            ylimValues=[-2,2];
        end
    end
    hold on
    xlim(xlimValues);
    ylim(ylimValues);
    axis off
    pause(1)
    
    % Grab a frame for the video, if making a video
    if makeVideo==1
        frame = getframe(1);
        writeVideo(writerObj, frame) 
    end
    
    % Repeat for the given number of iterations
    for i=1:iterations
        length=0.5*length/cosd(angle);
        
        % Clear the current axes
        cla
        
        % This will store the point values for the current iteration
        temp=[];
        
        % Repeat for each line segment
        for j=1:size(pts,1)
            
            % Grab the two endpoints of the current line segment
            pt1=pts(j,:);
            if j==size(pts,1)
                pt2=pts(1,:);
            else
                pt2=pts(j+1,:);
            end
            
            % Subtract the two points so you are centered at zero. Then
            % determine the current angle
            pt2corr=pt2-pt1;
            if 0>=pt2corr(1) && 0>=pt2corr(2)
                theta=atand(abs(pt2corr(2)/pt2corr(1)))+180;
            elseif 0>=pt2corr(1)
                theta=180-atand(abs(pt2corr(2)/pt2corr(1)));
            elseif 0>=pt2corr(2)
                theta=360-atand(abs(pt2corr(2)/pt2corr(1)));
            else
                theta=atand(abs(pt2corr(2)/pt2corr(1)));
            end       
            
            % Calculate the 'midpoint'; the top of the triangle drawn with
            % the current line segment as the base
            if inverted==1
                midpt=[length*cosd(theta+angle)+pt1(1),...
                    length*sind(theta+angle)+pt1(2)];
            else
                midpt=[length*cosd(theta-angle)+pt1(1),...
                    length*sind(theta-angle)+pt1(2)];
            end
            
            % Determine the line color based on the iteration
            c=[j/size(pts,1) 0 1-j/size(pts,1)];   
            
            % Plot the new line segments
            plot([pt1(1) midpt(1) pt2(1)],[pt1(2) midpt(2) pt2(2)],...
                'Color',c,'LineWidth',1)
            hold on
            xlim(xlimValues);
            ylim(ylimValues);
            axis off
            temp=[temp;pt1;midpt];
        end
        temp=[temp;pt2];
        
        % Store the points from the previous iteration in the pts variable
        pts=temp;
        
        % After plotting all the line segments in a given iteration, pause
        % to view the figure. And grab a frame if making a video. 
        pause(1)
        if makeVideo==1
            frame = getframe(1);
            writeVideo(writerObj, frame) 
        end        
    end
    
    % If you're making a video, add a couple of frames of the final image 
    if makeVideo==1
        for i=5
            frame = getframe(1);
            writeVideo(writerObj, frame) 
        end
        close(writerObj)
    end
end