polygon_triangulator.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. try:
  2. import PIL
  3. except ImportError:
  4. import os
  5. print("Trying to Install required module: Pillow\n")
  6. os.system('python get-pip.py')
  7. os.system('python -m pip install Pillow')
  8. pass
  9. try:
  10. import pyclipper
  11. except ImportError:
  12. import os
  13. print("Trying to Install required module: pyclipper\n")
  14. os.system('python get-pip.py')
  15. os.system('python -m pip install pyclipper')
  16. pass
  17. from PIL import Image,ImageDraw
  18. import earcut
  19. import pyclipper
  20. ERROR_OK=0
  21. ERROR_INVALID_POINTS=1
  22. SCALE_FACTOR=float(2**32) #100000000.0
  23. def scale_up(x):
  24. return x*SCALE_FACTOR
  25. def scale_down(x):
  26. return x/SCALE_FACTOR
  27. def parse_points(s):
  28. try:
  29. rv=[scale_up(float(v.strip())) for v in s.split()]
  30. rv=tuple(zip(*[iter(rv)]*2))
  31. return ERROR_OK,rv
  32. except:
  33. return ERROR_INVALID_POINTS,None
  34. def build_bb(x,y,w,h):
  35. x=scale_up(x)
  36. y=scale_up(y)
  37. w=scale_up(w)
  38. h=scale_up(h)
  39. return ((x,y),(x+w,y),(x+w,y+h),(x,y+h))
  40. # return ((0,0),(w-x*2,0),(w-x*2,h-y*2),(0,h-y*2))
  41. def apply_mask(src,mask,subtract):
  42. clipper=pyclipper.Pyclipper()
  43. clipper.AddPath(src,pyclipper.PT_SUBJECT,True)
  44. try:
  45. clipper.AddPath(mask,pyclipper.PT_CLIP,True)
  46. except pyclipper.ClipperException as ex:
  47. return None
  48. pass
  49. mode=pyclipper.CT_DIFFERENCE if subtract else pyclipper.CT_INTERSECTION
  50. rv=clipper.Execute(mode,pyclipper.PFT_EVENODD,pyclipper.PFT_EVENODD)
  51. return rv
  52. def order_clipped(polygons):
  53. hulls=[]
  54. holes=[]
  55. for poly in polygons:
  56. if pyclipper.Orientation(poly):
  57. hulls.append(poly)
  58. else:
  59. holes.append(poly)
  60. return hulls,holes
  61. def triangulate(hulls,holes):
  62. rv=[]
  63. for hull in hulls:
  64. data=earcut.flatten([hull]+holes)
  65. tris=earcut.earcut(data['vertices'],data['holes'],data['dimensions'])
  66. rv.append([data['vertices'],tris])
  67. return rv
  68. def combine_meshes(meshes):
  69. max_index=0
  70. rv_vertices={}
  71. rv_indices=[]
  72. for vertices,indices in meshes:
  73. vertices=tuple(zip(*[iter(vertices)]*2))
  74. for vertex in vertices:
  75. if vertex not in rv_vertices:
  76. rv_vertices[vertex]=max_index
  77. max_index+=1
  78. for index in indices:
  79. rv_indices.append(rv_vertices[vertices[index]])
  80. rv_vertices=[coord for vertex in sorted(rv_vertices,key=rv_vertices.get) for coord in vertex]
  81. return rv_vertices,rv_indices
  82. def generate_uv(x,y,w,h,vertices):
  83. rv=[]
  84. for n in range(0,len(vertices)//2):
  85. rv.append((vertices[n*2]-x)/w)
  86. rv.append((vertices[n*2+1]-y)/h)
  87. return rv
  88. def process(bb,base_width,base_height,trim_width,trim_height,trim_offset_x,trim_offset_y,subtract,points):
  89. if bb:
  90. src=build_bb(trim_offset_x,trim_offset_y,trim_width,trim_height)
  91. error,mask=parse_points(points)
  92. if error!=ERROR_OK:
  93. return error,None
  94. clipped=apply_mask(src,mask,subtract)
  95. else:
  96. error,mask=parse_points(points)
  97. if error!=ERROR_OK:
  98. return error,None
  99. clipped=apply_mask(mask,mask,False)
  100. if clipped is None:
  101. return ERROR_OK, (0, 0, [], [], [])
  102. pass
  103. hulls,holes=order_clipped(clipped)
  104. meshes=triangulate(hulls,holes)
  105. vertices,indices=combine_meshes(meshes)
  106. vertices=[scale_down(coord) for coord in vertices]
  107. uv=generate_uv(trim_offset_x,trim_offset_y,trim_width,trim_height,vertices)
  108. return ERROR_OK,(len(vertices)//2,len(indices),vertices,uv,indices)
  109. #if __name__=='__main__':
  110. # print(process(True,242.0,284.0,245.0,287.0,-1.0,-1.0,False,'163.39762878418 -22.0001831054688 69.4337463378906 -18.7153472900391 74.0543670654297 319.253051757813 172.017868041992 315.91357421875'))
  111. # print(process(True,242.0,284.0,245.0,287.0,-1.0,-1.0,True,'163.39762878418 -22.0001831054688 69.4337463378906 -18.7153472900391 74.0543670654297 319.253051757813 172.017868041992 315.91357421875'))
  112. # print(process(True,242.0,284.0,245.0,287.0,-1.0,-1.0,False,'163.397674560547 -22.0001678466797 -310.49951171875 -157.534454345703 -228.468200683594 429.399017333984 172.017913818359 315.913604736328'))
  113. # print(process(False,242.0,284.0,245.0,287.0,-1.0,-1.0,False,'163.397674560547 -22.0001678466797 -310.49951171875 -157.534454345703 -228.468200683594 429.399017333984 172.017913818359 315.913604736328'))