Advertisement
Guest User

Untitled

a guest
Nov 12th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.04 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. import numpy as np
  3. from sys import argv
  4.  
  5. def main(argv):
  6.     method = "cs"
  7.    
  8.     inputpath = argv[2]
  9.    
  10.     if len(argv) == 4:
  11.         if argv[3] == "-x":
  12.             method = "cb"
  13.    
  14.     outputpath = inputpath[0:len(inputpath)-3] + ".xpm"
  15.  
  16.     matrix = ['0'] * 500
  17.     for i in range(500):
  18.         matrix[i] = ['0'] * 500
  19.  
  20.     #checks if the file has begun
  21.     bof = False
  22.     #checks for end of file
  23.     eof = False
  24.    
  25.     inputfile = open(inputpath, "r")
  26.     outputfile = open(outputpath, "w")
  27.    
  28.     polygon = []
  29.    
  30.     while not eof:
  31.         line = inputfile.readline()
  32.        
  33.         polygonComplete = False
  34.        
  35.         if "%%%BEGIN" in line:
  36.             bof = True
  37.             line = inputfile.readline()
  38.         if "moveto" in line and bof:
  39.             input = line.split()
  40.             polygon = [(int(input[0]), int(input[1]))]
  41.         elif "lineto" in line and bof:
  42.             input = line.split()
  43.             polygon.append((int(input[0]), (int(input[1]))))
  44.         elif "stroke" in line and bof:
  45.             polygonComplete = True
  46.         if "%%%END" in line:
  47.             bof = False
  48.             eof = True
  49.  
  50.         if bof and len(line.split()) > 3 and line.split()[4] == "Line":
  51.             updatedArray = (getLineCoordinates(line.split()[0:4], method))
  52.             matrix = pairsToMatrix(updatedArray, matrix)
  53.         if bof and polygonComplete:
  54.             vertices = sutherlandHodgman(polygon)
  55.             updatedArray = (getPolygonCoordinates(vertices, polygon))
  56.             if vertices != []:
  57.                 matrix = scanFillPolygon(vertices, matrix)
  58.             matrix = pairsToMatrix(updatedArray, matrix)
  59.             polygonComplete = False
  60.        
  61.     convertToXPM(outputfile, matrix)
  62.    
  63. def getPolygonCoordinates(vertices, polygon):
  64.     updatedArray = []
  65.    
  66.     for i in range(len(vertices)):
  67.         if i + 1 == len(vertices):
  68.             coordinates = [vertices[i], vertices[0]]
  69.         else:
  70.             coordinates = [vertices[i], vertices[i + 1]]
  71.         new = drawLine(*coordinates[0], *coordinates[1])
  72.         updatedArray.extend(new)
  73.    
  74.     return updatedArray
  75.  
  76. def scanFillPolygon(vertices, matrix):
  77.     sortByY = sorted(vertices, key=lambda x: x[1])
  78.    
  79.     ymin = sortByY[0][1]
  80.     ymax = sortByY[len(sortByY)-1][1]
  81.     fill = []
  82.    
  83.     y = ymax - 1
  84.     while(y > ymin):
  85.         #get intersections of scan line
  86.         #for each edge
  87.         extrema = []
  88.         for i in range(len(vertices) - 1):
  89.             edge = False
  90.             if i == (len(vertices) - 1):
  91.                 if vertices[i][0] == 499 or vertices[0][0] == 499:
  92.                     edge = True
  93.                 elif vertices[i][0] == 0 or vertices[0][0] == 0:
  94.                     edge = True
  95.                 if vertices[i][1] != vertices[0][1] or edge:
  96.                     x = getXIntercept(y, vertices[i], vertices[0])
  97.                     if x != ():
  98.                         extrema.append(x)
  99.             else:
  100.                 if vertices[i][0] == 499 or vertices[i+1][0] == 499:
  101.                     edge = True
  102.                 elif vertices[i][0] == 0 or vertices[i+1][0] == 0:
  103.                     edge = True
  104.                 if vertices[i][1] != vertices[i + 1][1] or edge:
  105.                     x = getXIntercept(y, vertices[i], vertices[i + 1])
  106.                     if x != ():
  107.                         extrema.append(x)
  108.            
  109.         #add to list, check if y min or y max
  110.         #sort x ascending
  111.         extrema = sorted(extrema, key=lambda x: x[0])
  112.        
  113.         for i in range(0, len(extrema)-1, 2):
  114.             current = extrema[i][0]
  115.             next = extrema[i+1][0]
  116.            
  117.             for j in range(int(current), int(next)):
  118.                 fill.append((j,y))
  119.                
  120.             #change values of matrix, once it hits the first intersection, switches to 1 until it hits the 2nd intersection, doesn't fill in 1
  121.        
  122.         y = y - 1
  123.     return pairsToMatrix(fill, matrix)
  124.    
  125. def getXIntercept(y, endpoint1, endpoint2):
  126.     if endpoint1[0] == endpoint2[0]:
  127.         return (endpoint1[0],y)
  128.     elif endpoint1[1] < y and endpoint2[1] < y:
  129.         return ()
  130.     elif endpoint1[1] > y and endpoint2[1] > y:
  131.         return ()
  132.     else:
  133.         m = (endpoint2[1] - endpoint1[1])/(endpoint2[0] - endpoint1[0])
  134.        
  135.         x = endpoint1[0] + ((y - endpoint1[1]) / m)
  136.  
  137.         return (x,y)
  138.    
  139. def getLineCoordinates(array, method):
  140.     if method == "cs":
  141.         coordinates = cohenSutherland(array)
  142.        
  143.         if coordinates == []:
  144.             updatedArray = []
  145.         else:
  146.             updatedArray = drawLine(*coordinates[0], *coordinates[1])
  147.            
  148.     elif method == "cb":
  149.         p0 = (int(array[0]), int(array[1]))
  150.         p1 = (int(array[2]), int(array[3]))
  151.         coordinates = cyrusBeck(p0, p1)
  152.         if coordinates == []:
  153.             updatedArray = []
  154.         else:
  155.             updatedArray = drawLine(*coordinates[0], *coordinates[1])
  156.        
  157.     return updatedArray
  158.  
  159. def sutherlandHodgman(vertices):
  160.     updatedVertices = []
  161.  
  162.     for j in range(2):
  163.         for i in range(len(vertices)):
  164.             inout = []
  165.            
  166.             if vertices[i][j] < 0:
  167.                 inout.append("outside")
  168.             else:
  169.                 inout.append("inside")
  170.                
  171.             if (i + 1) == len(vertices):
  172.                 if vertices[0][j] < 0:
  173.                     inout.append("outside")
  174.                 else:
  175.                     inout.append("inside")
  176.             else:
  177.                 if vertices[i + 1][j] < 0:
  178.                     inout.append("outside")
  179.                 else:
  180.                     inout.append("inside")
  181.            
  182.             if inout[0] == "inside" and inout[1] == "inside":
  183.                 if (i + 1) == len(vertices):
  184.                     updatedVertices.append(vertices[0])
  185.                 else:
  186.                     updatedVertices.append(vertices[i + 1])
  187.             if inout[0] == "inside" and inout[1] == "outside":
  188.                 if (i + 1) == len(vertices):
  189.                     v = cyrusBeck(vertices[i], vertices[0])
  190.                 else:
  191.                     v = cyrusBeck(vertices[i], vertices[i + 1])
  192.                 if v != []:
  193.                     updatedVertices.append(v[1])
  194.             if inout[0] == "outside" and inout[1] == "inside":
  195.                 if (i + 1) == len(vertices):
  196.                     v = cyrusBeck(vertices[i], vertices[0])
  197.                 else:
  198.                     v = cyrusBeck(vertices[i], vertices[i + 1])
  199.                 if v != []:
  200.                     updatedVertices.append(v[0])
  201.                     updatedVertices.append(v[1])
  202.            
  203.         vertices = updatedVertices
  204.         updatedVertices = []
  205.  
  206.     for j in range(2):
  207.         for i in range(len(vertices)):
  208.             inout = []
  209.             if vertices[i][j] > 499:
  210.                 inout.append("outside")
  211.             else:
  212.                 inout.append("inside")
  213.                
  214.             if (i + 1) == len(vertices):
  215.                 if vertices[0][j] > 499:
  216.                     inout.append("outside")
  217.                 else:
  218.                     inout.append("inside")
  219.             else:
  220.                 if vertices[i + 1][j] > 499:
  221.                     inout.append("outside")
  222.                 else:
  223.                     inout.append("inside")
  224.            
  225.             if inout[0] == "inside" and inout[1] == "inside":
  226.                 if (i + 1) == len(vertices):
  227.                     updatedVertices.append(vertices[0])
  228.                 else:
  229.                     updatedVertices.append(vertices[i + 1])
  230.             if inout[0] == "inside" and inout[1] == "outside":
  231.                 if (i + 1) == len(vertices):
  232.                     v = cyrusBeck(vertices[i], vertices[0])
  233.                 else:
  234.                     v = cyrusBeck(vertices[i], vertices[i + 1])
  235.                 if v != []:
  236.                     updatedVertices.append(v[1])
  237.             if inout[0] == "outside" and inout[1] == "inside":
  238.                 if (i + 1) == len(vertices):
  239.                     v = cyrusBeck(vertices[i], vertices[0])
  240.                 else:
  241.                     v = cyrusBeck(vertices[i], vertices[i + 1])
  242.                 if v != []:
  243.                     updatedVertices.append(v[0])
  244.                     updatedVertices.append(v[1])
  245.            
  246.         vertices = updatedVertices
  247.         updatedVertices = []
  248.            
  249.     return vertices
  250.    
  251. def cohenSutherland(array):
  252.     coordinates = [(int(array[0]), int(array[1])),(int(array[2]), int(array[3]))]
  253.    
  254.     bitcode = [assignBitCode(*coordinates[0]), assignBitCode(*coordinates[1])]
  255.    
  256.     i = 0
  257.     outside = False
  258.     while i < 4:
  259.         if bitcode[0][i] == 1 and (bitcode[0][i] == bitcode[1][i]):
  260.             outside = True
  261.         i = i + 1
  262.    
  263.     if outside:
  264.         return []
  265.     elif 1 in bitcode[0] or 1 in bitcode[1]:
  266.         return clipLine(bitcode, coordinates)
  267.     elif (1 not in bitcode[0] and 1 not in bitcode[1]):
  268.         return coordinates
  269.  
  270. def assignBitCode(x, y):
  271.     bitcode = [0,0,0,0]
  272.    
  273.     if y < 0:
  274.         bitcode[1] = 1
  275.     if x < 0:
  276.         bitcode[3] = 1
  277.     if y > 499:
  278.         bitcode[0] = 1
  279.     if x > 499:
  280.         bitcode[2] = 1
  281.    
  282.     return bitcode
  283.    
  284. def clipLine(bitcode, currentCoordinates):
  285.     if (currentCoordinates[1][0] - currentCoordinates[0][0]) == 0:
  286.         if 1 in bitcode[0]:
  287.             if bitcode[0][0] == 1:
  288.                 currentCoordinates[0][1] = 499
  289.             elif bitcode[0][1] == 1:
  290.                 currentCoordinates[0][1] = 0
  291.            
  292.         if 1 in bitcode[1]:
  293.             if bitcode[1][0] == 1:
  294.                 currentCoordinates[1][1] = 499
  295.             elif bitcode[1][1] == 1:
  296.                 currentCoordinates[1][1] = 0
  297.     else:
  298.         m = (currentCoordinates[1][1] - currentCoordinates[0][1]) / (currentCoordinates[1][0] - currentCoordinates[0][0])
  299.        
  300.         if 1 in bitcode[0]:
  301.             if bitcode[0][0] == 1:
  302.                 x = currentCoordinates[0][0] + ((499 - currentCoordinates[0][1]) / m)
  303.                 currentCoordinates[0][0] = x
  304.                 currentCoordinates[0][1] = 499
  305.             elif bitcode[0][1] == 1:
  306.                 x = currentCoordinates[0][0] - (currentCoordinates[0][1] / m)
  307.                 currentCoordinates[0][0] = x
  308.                 currentCoordinates[0][1] = 0
  309.                
  310.             bitcode[0] = assignBitCode(*currentCoordinates[0])
  311.            
  312.             if bitcode[0][2] == 1:
  313.                 y = currentCoordinates[0][1] + (m * (499 - currentCoordinates[0][0]))
  314.                 currentCoordinates[0][1] = y
  315.                 currentCoordinates[0][0] = 499
  316.             elif bitcode[0][3] == 1:
  317.                 y = currentCoordinates[0][1] - (m * currentCoordinates[0][0])
  318.                 currentCoordinates[0][1] = y
  319.                 currentCoordinates[0][0] = 0
  320.                
  321.         if 1 in bitcode[1]:
  322.             if bitcode[1][0] == 1:
  323.                 x = currentCoordinates[1][0] + ((499 - currentCoordinates[1][1]) / m)
  324.                 currentCoordinates[1][0] = x
  325.                 currentCoordinates[1][1] = 499
  326.             elif bitcode[1][1] == 1:
  327.                 x = currentCoordinates[1][0] - (currentCoordinates[1][1] / m)
  328.                 currentCoordinates[1][0] = x
  329.                 currentCoordinates[1][1] = 0
  330.                
  331.             bitcode[1] = assignBitCode(*currentCoordinates[1])
  332.            
  333.             if bitcode[1][2] == 1:
  334.                 y = currentCoordinates[1][1] + (m * (499 - currentCoordinates[1][0]))
  335.                 currentCoordinates[1][1] = y
  336.                 currentCoordinates[1][0] = 499
  337.             elif bitcode[1][3] == 1:
  338.                 y = currentCoordinates[1][1] - (m * currentCoordinates[1][0])
  339.                 currentCoordinates[1][1] = y
  340.                 currentCoordinates[1][0] = 0
  341.            
  342.     return currentCoordinates
  343.        
  344.        
  345. def drawLine(x1, y1, x2, y2):
  346.     yk = y1
  347.     xk = x1
  348.  
  349.     deltax = x2 - x1
  350.     deltay = y2 - y1
  351.    
  352.     if deltax == 0:
  353.         updatedArray = [(xk, yk)]
  354.         while yk - 1 > y2:
  355.             yk = yk - 1
  356.             updatedArray.append((xk, yk))
  357.         while yk + 1 < y2:
  358.             yk = yk + 1
  359.             updatedArray.append((xk, yk))
  360.         return updatedArray
  361.        
  362.     m = deltay / deltax
  363.  
  364.     if abs(m) < 1:
  365.         if(x1 > x2):
  366.             xk = x2
  367.             x2 = x1
  368.             yk = y2
  369.             y2 = y1
  370.        
  371.         deltax = 1
  372.         deltay = (y2 - yk) / (x2 - xk)
  373.  
  374.         updatedArray = [(xk, yk)]
  375.        
  376.         while xk + deltax < x2:
  377.             xk = xk + deltax
  378.             yk = yk + deltay
  379.             updatedArray.append((xk, yk))
  380.  
  381.     else:
  382.         if(y1 > y2):
  383.             xk = x2
  384.             x2 = x1
  385.             yk = y2
  386.             y2 = y1
  387.            
  388.         m = (y2 - yk) / (x2 - xk)
  389.         deltay = 1
  390.         deltax = 1 / m
  391.  
  392.         updatedArray = [(xk, yk)]
  393.        
  394.         while yk + deltay < y2:
  395.             yk = yk + deltay
  396.             xk = xk + deltax
  397.             updatedArray.append((xk, yk))
  398.    
  399.     return updatedArray
  400.    
  401.    
  402. def pairsToMatrix(updatedArray, matrix):
  403.     for i in updatedArray:
  404.         x = round(float(i[0]))
  405.         y = round(float(i[1]))
  406.         matrix[x][y] = '1'
  407.     return matrix
  408.  
  409. def convertToXPM(outputfile, matrix):
  410.     outputfile.write("/* XPM */ \n")
  411.     outputfile.write("static char *sco100[] = { \n")
  412.    
  413.     outputfile.write("/* width height num_colors chars_per_pixel */ \n")
  414.     outputfile.write("\"500 500 2 1\", \n")
  415.    
  416.     outputfile.write("/* colors */ \n")
  417.     outputfile.write("\"0 c #ffffff\", \n")
  418.     outputfile.write("\"1 c #000000\", \n")
  419.    
  420.     outputfile.write("/* pixels */ \n")
  421.    
  422.     matrix = np.rot90(matrix, k=1)
  423.    
  424.     temp = "\""""
  425.  
  426.     k = 0
  427.     for i in matrix:
  428.         k = k + 1
  429.         for j in i:
  430.             temp = temp + str(j)
  431.         if(k == len(matrix)):
  432.             temp = temp + "\"""\n"
  433.         else:
  434.             temp = temp + "\""",\n\""""
  435.     temp = temp + "};"
  436.    
  437.     outputfile.write(temp)
  438.    
  439. def cyrusBeck(p0, p1)
  440.     normal = [(-1, 0),(0, -1),(0, 1),(1, 0)]
  441.     entering = [0]
  442.     leaving = [1]
  443.    
  444.     gridpoints = [(0, 0),(499, 0),(0, 499),(499, 499)]
  445.     d = subtractVectors(p1, p0)
  446.    
  447.     for i in range(4):
  448.         type = dotProduct(normal[i], d)
  449.        
  450.         if type == 0:
  451.             continue
  452.            
  453.         t = (dotProduct(normal[i], (subtractVectors(p0, gridpoints[i]))) / type) * -1
  454.        
  455.         if type > 0:
  456.             leaving.append(t)
  457.         elif type < 0:
  458.             entering.append(t)
  459.    
  460.     timeEntering = max(entering)
  461.     timeLeaving = min(leaving)
  462.    
  463.     pte = addVectors(p0, multiplyVectors(timeEntering, d))
  464.     ptl = addVectors(p0, multiplyVectors(timeLeaving, d))
  465.    
  466.     if timeEntering > timeLeaving:
  467.         return []
  468.     elif any((c < 0 or c > 499) for c in [*pte, *ptl]):
  469.         return []
  470.     else:
  471.         return [pte, ptl]
  472.    
  473. def subtractVectors(v1, v2):
  474.     return ((v1[0] - v2[0]),(v1[1] - v2[1]))
  475.  
  476. def addVectors(v1, v2):
  477.     return ((v1[0] + v2[0]),(v1[1] + v2[1]))
  478.    
  479. def multiplyVectors(c, v):
  480.     return ((c * v[0]),(c * v[1]))
  481.    
  482. def dotProduct(v1, v2):
  483.     return sum(x * y for (x, y) in zip(v1, v2))
  484.    
  485. main(argv)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement