user:mate2code/bin2svg

From Wikiversity
Jump to: navigation, search
Binary matrix to SVG path
Sierpinski triangle drawn with bin2svg - The red squares form one continuous area, so the path contains only one M.

bin2svg.m is a Matlab program I have written to represent binary matrices as vector graphics.
The input is the binary matrix and the output is the code of the corresponding SVG path.
Matrices created with this program are marked with {{Created with bin2svg}} and sorted into the hidden category Created with bin2svg.


Function bin2svg[edit]

Subfunction bin2corners[edit]

function [y] = bin2corners(x)
% Turns the binary matrix in a bigger matrix with key numbers.
high = size(x,1) ;
long = size(x,2) ;
X = [  zeros(1,long+2) ;
       zeros(high,1) x zeros(high,1) ;
       zeros(1,long+2) ] ;
Y = zeros(high+1,long+1) ;
for m=1:high+1
    for n=1:long+1
        A = X(m:m+1,n:n+1) ;
            if A == [ 0 0 ; 0 1 ] 
               Y(m,n) = 1 ;
        elseif A == [ 0 0 ; 1 0 ] 
               Y(m,n) = 2 ;
        elseif A == [ 1 0 ; 0 0 ] 
               Y(m,n) = 3 ;
        elseif A == [ 0 1 ; 0 0 ] 
               Y(m,n) = 4 ;
        elseif A == [ 1 1 ; 1 0 ] 
               Y(m,n) = 5 ;
        elseif A == [ 1 0 ; 1 1 ] 
               Y(m,n) = 6 ;
        elseif A == [ 0 1 ; 1 1 ] 
               Y(m,n) = 7 ;
        elseif A == [ 1 1 ; 0 1 ] 
               Y(m,n) = 8 ;
        elseif A == [ 1 0 ; 0 1 ] 
               Y(m,n) = 13 ;
        elseif A == [ 0 1 ; 1 0 ] 
               Y(m,n) = 24 ;
           end
    end
end
y = Y ;
end


Subfunction cornerfinder[edit]

function [y] = cornerfinder(x1,x2)
% Searches matrix x1 from position x2 for non zero entries.
% Output is vector [m n k] where [m n] is the first position found and k the entry at this position.
high = size(x1,1) ;
wide = size(x1,2) ;
look = x2 ;
found = 0 ;
while found == 0   
      found = x1( look(1) , look(2) ) ;       
      if found == 0         
         if look(2) < wide
            look(2) = look(2) + 1 ;
         elseif look(2)==wide && look(1)<high
            look = [ look(1)+1  1 ] ;
         else
             look = [-1 -1] ;     % reached end, signal to stop for other function
             break
         end
      else break
      end      
end
y = [ look found ]  ;
end


Subfunction bin2svg_step[edit]

function [y] = bin2svg_step(mat,x2)
% x1 is the key number matrix, x2 is the output of cornerfinder.
pos = x2(1:2) ;
coordinates = [ 'M' num2str(pos(2)-1) ',' num2str(pos(1)-1) ] ;
entry = x2(3) ;
while 1
    if entry>=1 && entry<=8
       mat(pos(1),pos(2)) = 0 ;
    elseif entry==13 && ( entrybefore==4 || entrybefore==7 )        % 13 as 1 , leave 3
       mat(pos(1),pos(2)) = 3 ;                                     entry = 1 ;
    elseif entry==13 && ( entrybefore==2 || entrybefore==5 )        % 13 as 3 , leave 1
       mat(pos(1),pos(2)) = 1 ;                                     entry = 3 ;
    elseif entry==24 && ( entrybefore==1 || entrybefore==6 )        % 24 as 2 , leave 4
       mat(pos(1),pos(2)) = 4 ;                                     entry = 2 ;
    elseif entry==24 && ( entrybefore==3 || entrybefore==8 )        % 24 as 4 , leave 2
       mat(pos(1),pos(2)) = 2 ;                                     entry = 4 ;
    end
    posbefore = pos ;
    creeper = 0 ;
    if     entry==1 || entry==6
       while creeper == 0
             pos(2) = pos(2)+1 ;
             if pos == x2(1:2)
                 break
             end
             creeper = mat( pos(1) , pos(2) ) ;      
       end
    elseif entry==2 || entry==5
       while creeper == 0
             pos(1) = pos(1)+1 ; 
             if pos == x2(1:2)
                 break
             end
             creeper = mat( pos(1) , pos(2) ) ; 
       end
    elseif entry==3 || entry==8
       while creeper == 0
             pos(2) = pos(2)-1 ;   
             if pos == x2(1:2)
                 break
             end
             creeper = mat( pos(1) , pos(2) ) ; 
       end
    elseif entry==4 || entry==7
       while creeper == 0
             pos(1) = pos(1)-1 ;  
             if pos == x2(1:2)
                 break
             end
             creeper = mat( pos(1) , pos(2) ) ; 
       end
    end
    entrybefore = entry ;
    entry = creeper ;
    if   pos(1)==posbefore(1)
         d = [ 'h' num2str( pos(2)-posbefore(2) ) ] ;
    else
         d = [ 'v' num2str( pos(1)-posbefore(1) ) ] ;
    end
    if pos == x2(1:2)
    break
    end 
    coordinates = [ coordinates d ] ;
end
Y = cell(1,2);
Y{1} = mat ;
Y{2} = coordinates ;
y = Y ;
end


Function bin2svg itself[edit]

function [y] = bin2svg(x)
% Binary matrix to SVG path.
A = bin2corners(x) ;
startpos = [1 1] ;
coordinates = repmat(' ',1,0) ;
while 1
        B = cornerfinder(A,startpos) ;
        if B == [-1 -1 0]
            break
        end
        startpos = B(1:2) ;
        C = bin2svg_step(A,B) ;
        A = C{1} ;
        coordinates = [ coordinates C{2} ] ;
end  
y = coordinates ;
end
binmat as SVG

Example:

>> binmat
binmat =
     0     0     0     1
     1     1     1     0
     1     0     1     0
     1     1     1     0
>> bin2svg(binmat)
ans =
M3,0h1v1h-1M0,1h3v3h-3M1,2v1h1v-1

In the following SVG code the result produces the image shown on the right:

<? xml version = "1.0" encoding = "UTF-8" ?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="-.5 -.5 5 5">
    <path fill="#fff" d="m0,0h4v4H0"/> <!-- white background -->
    <path fill="#f00" d="M3,0h1v1h-1M0,1h3v3h-3M1,2v1h1v-1"/> <!-- red entries -->
    <g stroke="#000">
        <path stroke-width="4" stroke-dasharray=".05,.95" d="M0,2h5M2,0v5"/> <!-- 0.5px black lines -->
        <rect stroke-width=".1" fill="none" x="0" y="0" width="4" height="4"/> <!-- 1px black square -->
    </g>
</svg>

Derived functions for integer matrices[edit]

Binary strings created with mat2svg(Matrix,4,5,2)
Binary matrices below are created with mat2svg_dual(Matrix,4,3)
Binary strings created with mat2svg(Matrix,16,8,2)
Binary matrices below are created with mat2svg_dual(Matrix,16,2)



mat2svg[edit]

function [Code] = mat2svg(Mat,Bitlong,Gapvert,Gaphorz)
% Produces the SVG code for binary strings in an SVG graphic of a matrix of integers.
% Inputs: ( matrix, length of binary strings, size of vertical gaps, size of horizontal gaps )
 
% used functions: bin2svg, char2mat
 
Matvert = size(Mat,1) ;
Mathorz = size(Mat,2) ;
 
Bin = zeros(   Matvert + (Matvert-1)*Gapvert   ,   Mathorz*Bitlong + (Mathorz-1)*Gaphorz   ) ;
 
for m=1:Matvert
    for n=1:Mathorz
        Bin( (m-1)*(Gapvert+1)+1 , (n-1)*(Bitlong+Gaphorz)+1 : (n-1)*(Bitlong+Gaphorz)+Bitlong ) = char2mat( dec2bin(Mat(m,n),Bitlong) ) ; 
    end
end
 
Code = bin2svg( Bin ) ;
 
end


mat2svg_dual[edit]

function [Code] = mat2svg_dual(Mat,Bitlong,Gap)
% Produces the SVG code for binary dual matrix in an SVG graphic of a matrix of integers.
% Inputs: ( matrix, length of binary strings, size of gap between matrices )
 
% used functions: bin2svg, char2mat
 
Matvert = size(Mat,1) ;
Mathorz = size(Mat,2) ;
 
Binmat = zeros(   Matvert   ,   Mathorz*Bitlong + (Bitlong-1)*Gap   ) ;
 
for m=1:Matvert
    for n=1:Mathorz
        Binvect = char2mat( dec2bin(Mat(m,n),Bitlong) ) ;
        for k=1:Bitlong
            Binmat( m , (Mathorz+Gap)*(k-1)+n ) = Binvect(k) ;
        end
    end
end
 
Code = bin2svg( Binmat ) ;
 
end