Advertisement
mate2code

bin2svg.py

Jan 24th, 2015
792
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.45 KB | None | 0 0
  1. import numpy as np
  2.  
  3.  
  4. def bin2svg(tosvg):
  5.     """
  6.    :param tosvg: numpy array with binary entries, e.g. `np.array([[1, 0],
  7.                                                                   [0, 1]])`
  8.    :return: string describing an SVG path, e.g. 'M0,0h1v1h-1M1,1h1v1h-1'
  9.  
  10.    see also: https://en.wikiversity.org/wiki/User:Watchduck/bin2svg
  11.    """
  12.  
  13.     def bin2corners(tocorners):
  14.         """
  15.        :param tocorners: binary m×n matrix; areas of 1s to be interpreted as areas of squares with no internal corners
  16.        :return: m+1 × n+1 matrix; 0 for no corner; 1, 2, 3, 4 for corner; 13, 24 for double corner
  17.        """
  18.  
  19.         if type(tocorners) is not np.ndarray:  # if input is plain array
  20.             tocorners = np.array(tocorners)    # convert to numpy array
  21.  
  22.         (high, wide) = tocorners.shape
  23.         hpad = np.zeros((1, wide+2), np.int8)
  24.         vpad = np.zeros((high, 1), np.int8)
  25.         tocorners = np.vstack((
  26.             hpad,
  27.             np.hstack((vpad, tocorners, vpad)),
  28.             hpad
  29.         ))
  30.  
  31.         corners = np.zeros((high+1, wide+1), np.int8)
  32.  
  33.         for m in range(high+1):
  34.             for n in range(wide+1):
  35.                 sub = tocorners[m:m+2, n:n+2]
  36.                 if np.array_equal(sub, np.array([[0, 0],
  37.                                                  [0, 1]])):
  38.                     corners[m, n] = 1
  39.                 elif np.array_equal(sub, np.array([[0, 0],
  40.                                                    [1, 0]])):
  41.                     corners[m, n] = 2
  42.                 elif np.array_equal(sub, np.array([[1, 0],
  43.                                                    [0, 0]])):
  44.                     corners[m, n] = 3
  45.                 elif np.array_equal(sub, np.array([[0, 1],
  46.                                                    [0, 0]])):
  47.                     corners[m, n] = 4
  48.                 elif np.array_equal(sub, np.array([[1, 1],
  49.                                                    [1, 0]])):
  50.                     corners[m, n] = 5
  51.                 elif np.array_equal(sub, np.array([[1, 0],
  52.                                                    [1, 1]])):
  53.                     corners[m, n] = 6
  54.                 elif np.array_equal(sub, np.array([[0, 1],
  55.                                                    [1, 1]])):
  56.                     corners[m, n] = 7
  57.                 elif np.array_equal(sub, np.array([[1, 1],
  58.                                                    [0, 1]])):
  59.                     corners[m, n] = 8
  60.                 elif np.array_equal(sub, np.array([[1, 0],
  61.                                                    [0, 1]])):
  62.                     corners[m, n] = 13
  63.                 elif np.array_equal(sub, np.array([[0, 1],
  64.                                                    [1, 0]])):
  65.                     corners[m, n] = 24
  66.  
  67.         return corners
  68.  
  69.     def cornerfinder(corners, look):
  70.         """
  71.        Searches corner matrix from last position for non zero entries.
  72.        :param corners: current corner matrix
  73.        :param look: position where to begin searching
  74.        :return: {'pos': [m, n], 'val': k} where [m, n] is the first position found and k the entry at this position
  75.        """
  76.  
  77.         (high, wide) = corners.shape
  78.         found = 0
  79.  
  80.         while found == 0:
  81.             found = corners[tuple(look)]
  82.             if found == 0:
  83.                 if look[1] < wide-1:
  84.                     look[1] += 1
  85.                 elif look[1] == wide-1 and look[0] < high-1:
  86.                     look = [look[0]+1, 0]
  87.                 else:
  88.                     return 'reached end'
  89.             else:
  90.                 return {'pos': look, 'val': found}
  91.  
  92.     def step(corners, cornerfound):
  93.         """
  94.        :param corners: current corner matrix
  95.        :param cornerfound: last position and value found by `cornerfinder`
  96.        :return: {'corners': corners, 'svgpath': svgpath} with `corners` sparser and `svgpath` extended
  97.        """
  98.  
  99.         startpos = cornerfound['pos']
  100.         pos = startpos[:]
  101.         val = cornerfound['val']
  102.  
  103.         svgpath = 'M' + str(pos[1]) + ',' + str(pos[0])
  104.  
  105.         while True:
  106.  
  107.             if val in range(1, 9):  # 1 <= val <= 8
  108.                 corners[tuple(pos)] = 0
  109.             elif val == 13 and (oldval in [4, 7]):  # 13 as 1 , leave 3
  110.                 val = 1
  111.                 corners[tuple(pos)] = 3
  112.             elif val == 13 and (oldval in [2, 5]):  # 13 as 3 , leave 1
  113.                 val = 3
  114.                 corners[tuple(pos)] = 1
  115.             elif val == 24 and (oldval in [1, 6]):  # 24 as 2 , leave 4
  116.                 val = 2
  117.                 corners[tuple(pos)] = 4
  118.             elif val == 24 and (oldval in [3, 8]):  # 24 as 4 , leave 2
  119.                 val = 4
  120.                 corners[tuple(pos)] = 2
  121.  
  122.             oldpos = pos[:]
  123.  
  124.             creeper = 0
  125.  
  126.             if val in [1, 6]:
  127.                 while creeper == 0:
  128.                     pos[1] += 1
  129.                     if pos == startpos:
  130.                         break
  131.                     creeper = corners[tuple(pos)]
  132.             elif val in [2, 5]:
  133.                 while creeper == 0:
  134.                     pos[0] += 1
  135.                     if pos == startpos:
  136.                         break
  137.                     creeper = corners[tuple(pos)]
  138.             elif val in [3, 8]:
  139.                 while creeper == 0:
  140.                     pos[1] -= 1
  141.                     if pos == startpos:
  142.                         break
  143.                     creeper = corners[tuple(pos)]
  144.             elif val in [4, 7]:
  145.                 while creeper == 0:
  146.                     pos[0] -= 1
  147.                     if pos == startpos:
  148.                         break
  149.                     creeper = corners[tuple(pos)]
  150.  
  151.             oldval = val
  152.             val = creeper
  153.  
  154.             if pos[0] == oldpos[0]:
  155.                 append_to_svgpath = 'h' + str(pos[1]-oldpos[1])
  156.             else:
  157.                 append_to_svgpath = 'v' + str(pos[0]-oldpos[0])
  158.  
  159.             if pos == startpos:
  160.                 break
  161.  
  162.             svgpath += append_to_svgpath
  163.  
  164.         return {'corners': corners, 'svgpath': svgpath}
  165.  
  166.     corners = bin2corners(tosvg)
  167.     startpos = [0, 0]
  168.     svgpath = ''
  169.  
  170.     while True:
  171.         cornerfound = cornerfinder(corners, startpos)
  172.         if cornerfound == 'reached end':
  173.             break
  174.         startpos = cornerfound['pos']
  175.         thisstep = step(corners, cornerfound)
  176.         corners = thisstep['corners']
  177.         svgpath += thisstep['svgpath']
  178.  
  179.     return svgpath
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement