ToolPDF.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. ############################################################
  2. # FlatCAM: 2D Post-processing for Manufacturing #
  3. # http://flatcam.org #
  4. # File Author: Marius Adrian Stanciu (c) #
  5. # Date: 3/10/2019 #
  6. # MIT Licence #
  7. ############################################################
  8. from FlatCAMTool import FlatCAMTool
  9. from FlatCAMObj import *
  10. import math
  11. import numpy as np
  12. import scipy.interpolate
  13. import zlib
  14. import re
  15. import gettext
  16. import FlatCAMTranslation as fcTranslate
  17. fcTranslate.apply_language('strings')
  18. import builtins
  19. if '_' not in builtins.__dict__:
  20. _ = gettext.gettext
  21. class ToolPDF(FlatCAMTool):
  22. '''
  23. Parse a PDF file.
  24. Reference here: https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/pdf_reference_archives/PDFReference.pdf
  25. Return a list of geometries
  26. '''
  27. toolName = _("PDF Import Tool")
  28. def __init__(self, app):
  29. FlatCAMTool.__init__(self, app)
  30. self.app = app
  31. self.step_per_circles = self.app.defaults["gerber_circle_steps"]
  32. self.stream_re = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)
  33. # detect 'w' command
  34. self.strokewidth_re = re.compile(r'^(\d+\.?\d*)\s*w$')
  35. # detect 're' command
  36. self.rect_re = re.compile(r'^(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\sre$')
  37. # detect 'm' command
  38. self.start_path_re = re.compile(r'(-?\d+\.?\d*)\s(-?\d+\.?\d*)\sm$')
  39. # detect 'l' command
  40. self.draw_line_re = re.compile(r'(-?\d+\.?\d*)\s(-?\d+\.?\d*)\sl')
  41. # detect 'c' command
  42. self.draw_arc_3pt_re = re.compile(r'(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\sc$')
  43. # detect 'v' command
  44. self.draw_arc_2pt_23_re = re.compile(r'(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\sv$')
  45. # detect 'y' command
  46. self.draw_arc_2pt_13_re = re.compile(r'(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\sy$')
  47. # detect 'h' command
  48. self.end_path_re = re.compile(r'^h$')
  49. self.pdf_parsed = ''
  50. def run(self, toggle=True):
  51. self.app.report_usage("ToolPDF()")
  52. # if toggle:
  53. # # if the splitter is hidden, display it, else hide it but only if the current widget is the same
  54. # if self.app.ui.splitter.sizes()[0] == 0:
  55. # self.app.ui.splitter.setSizes([1, 1])
  56. # else:
  57. # try:
  58. # if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
  59. # self.app.ui.splitter.setSizes([0, 1])
  60. # except AttributeError:
  61. # pass
  62. # else:
  63. # if self.app.ui.splitter.sizes()[0] == 0:
  64. # self.app.ui.splitter.setSizes([1, 1])
  65. #
  66. # FlatCAMTool.run(self)
  67. self.set_tool_ui()
  68. self.on_open_pdf_click()
  69. # self.app.ui.notebook.setTabText(2, "PDF Tool")
  70. def install(self, icon=None, separator=None, **kwargs):
  71. FlatCAMTool.install(self, icon, separator, shortcut='ALT+Q', **kwargs)
  72. def set_tool_ui(self):
  73. pass
  74. def on_open_pdf_click(self):
  75. """
  76. File menu callback for opening an PDF file.
  77. :return: None
  78. """
  79. self.app.report_usage("ToolPDF.on_open_pdf_click()")
  80. self.app.log.debug("ToolPDF.on_open_pdf_click()")
  81. _filter_ = "Adobe PDF Files (*.pdf);;" \
  82. "All Files (*.*)"
  83. try:
  84. filenames, _f = QtWidgets.QFileDialog.getOpenFileNames(caption=_("Open PDF"),
  85. directory=self.app.get_last_folder(), filter=_filter_)
  86. except TypeError:
  87. filenames, _f = QtWidgets.QFileDialog.getOpenFileNames(caption=_("Open PDF"), filter=_filter_)
  88. filenames = [str(filename) for filename in filenames]
  89. if len(filenames) == 0:
  90. self.app.inform.emit(_("[WARNING_NOTCL] Open PDF cancelled."))
  91. else:
  92. for filename in filenames:
  93. if filename != '':
  94. self.app.worker_task.emit({'fcn': self.open_pdf,
  95. 'params': [filename]})
  96. def open_pdf(self, filename):
  97. def obj_init(grb_obj, app_obj):
  98. with open(filename, "rb") as f:
  99. pdf = f.read()
  100. for s in re.findall(self.stream_re, pdf):
  101. s = s.strip(b'\r\n')
  102. try:
  103. self.pdf_parsed += zlib.decompress(s).decode('UTF-8')
  104. except:
  105. pass
  106. grb_obj.solid_geometry = [self.bezier_to_linestring(0, 0, 0, 0)]
  107. with self.app.proc_container.new(_("Opening PDF.")):
  108. # obj_init()
  109. self.parse_pdf()
  110. ret = self.app.new_object("geometry", "bla", obj_init, autoselected=False)
  111. # Register recent file
  112. self.app.file_opened.emit("geometry", "bla")
  113. # # Object name
  114. # name = outname or filename.split('/')[-1].split('\\')[-1]
  115. #
  116. # ret = self.new_object("excellon", name, obj_init, autoselected=False)
  117. # if ret == 'fail':
  118. # self.inform.emit(_('[ERROR_NOTCL] Open Excellon file failed. Probable not an Excellon file.'))
  119. # return
  120. #
  121. # # Register recent file
  122. # self.file_opened.emit("excellon", filename)
  123. #
  124. # # GUI feedback
  125. # self.inform.emit(_("[success] Opened: %s") % filename)
  126. # # self.progress.emit(100)
  127. def parse_pdf(self):
  128. for pline in self.pdf_parsed:
  129. pass
  130. def bezier_to_linestring(self, start, stop, c1, c2):
  131. """
  132. From here: https://gis.stackexchange.com/questions/106937/python-library-or-algorithm-to-generate-arc-geometry-from-three-coordinate-pairs
  133. :return: LineString geometry
  134. """
  135. coords = np.array([[0, 0], [25, 10], [33, 39], [53, 53]])
  136. # equation Bezier, page 184 PDF 1.4 reference
  137. # https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/pdf_reference_archives/PDFReference.pdf
  138. # R(t) = P0*(1 - t) ** 3 + P1*3*t*(1 - 5) ** 2 + P2 * 3*(1 - t) * t ** 2 + P3*t ** 3
  139. domain = []
  140. i = 0
  141. while i <=1:
  142. domain.append(i)
  143. for i in domain:
  144. return even_line