VisPyPatches.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. # ##########################################################
  2. # FlatCAM: 2D Post-processing for Manufacturing #
  3. # http://flatcam.org #
  4. # File Author: Dennis Hayrullin #
  5. # Date: 2/5/2016 #
  6. # MIT Licence #
  7. # ##########################################################
  8. # ##########################################################
  9. # File Modified : Marcos Dumay de Medeiros #
  10. # Modifications under GPLv3 #
  11. # ##########################################################
  12. from vispy.visuals import markers, LineVisual, InfiniteLineVisual
  13. from vispy.visuals.axis import Ticker, _get_ticks_talbot
  14. from vispy.scene.widgets import Grid
  15. import numpy as np
  16. def apply_patches():
  17. # Patch MarkersVisual to have crossed lines marker
  18. cross_lines = """
  19. float cross(vec2 pointcoord, float size)
  20. {
  21. //vbar
  22. float r1 = abs(pointcoord.x - 0.5)*size;
  23. float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2;
  24. float vbar = max(r1,r2);
  25. //hbar
  26. float r3 = abs(pointcoord.y - 0.5)*size;
  27. float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2;
  28. float hbar = max(r3,r4);
  29. return min(vbar, hbar);
  30. }
  31. """
  32. #markers._marker_dict['++'] = cross_lines
  33. #markers.marker_types = tuple(sorted(list(markers._marker_dict.copy().keys())))
  34. # # Add clear_data method to LineVisual to have possibility of clearing data
  35. # def clear_data(self):
  36. # self._bounds = None
  37. # self._pos = None
  38. # self._changed['pos'] = True
  39. # self.update()
  40. #
  41. # LineVisual.clear_data = clear_data
  42. # Patch VisPy Grid to prevent updating layout on PaintGL, which cause low fps
  43. def _prepare_draw(self, view):
  44. pass
  45. def _update_clipper(self):
  46. super(Grid, self)._update_clipper()
  47. try:
  48. self._update_child_widget_dim()
  49. except Exception as e:
  50. print("VisPyPatches.apply_patches._update_clipper() -> %s" % str(e))
  51. Grid._prepare_draw = _prepare_draw
  52. Grid._update_clipper = _update_clipper
  53. # Patch InfiniteLine visual to 1px width
  54. def _prepare_draw(self, view=None):
  55. """This method is called immediately before each draw.
  56. The *view* argument indicates which view is about to be drawn.
  57. """
  58. GL = None
  59. from vispy.app._default_app import default_app
  60. if default_app is not None and \
  61. default_app.backend_name != 'ipynb_webgl':
  62. try:
  63. import OpenGL.GL as GL
  64. except Exception: # can be other than ImportError sometimes
  65. pass
  66. if GL:
  67. GL.glDisable(GL.GL_LINE_SMOOTH)
  68. GL.glLineWidth(2.0)
  69. if self._changed['pos']:
  70. self.pos_buf.set_data(self._pos)
  71. self._changed['pos'] = False
  72. if self._changed['color']:
  73. self._program.vert['color'] = self._color
  74. self._changed['color'] = False
  75. InfiniteLineVisual._prepare_draw = _prepare_draw
  76. # Patch AxisVisual to have less axis labels
  77. def _get_tick_frac_labels(self):
  78. """Get the major ticks, minor ticks, and major labels"""
  79. minor_num = 4 # number of minor ticks per major division
  80. if self.axis.scale_type == 'linear':
  81. domain = self.axis.domain
  82. if domain[1] < domain[0]:
  83. flip = True
  84. domain = domain[::-1]
  85. else:
  86. flip = False
  87. offset = domain[0]
  88. scale = domain[1] - domain[0]
  89. transforms = self.axis.transforms
  90. length = self.axis.pos[1] - self.axis.pos[0] # in logical coords
  91. n_inches = np.sqrt(np.sum(length ** 2)) / transforms.dpi
  92. # major = np.linspace(domain[0], domain[1], num=11)
  93. # major = MaxNLocator(10).tick_values(*domain)
  94. major = _get_ticks_talbot(domain[0], domain[1], n_inches, 1)
  95. labels = ['%g' % x for x in major]
  96. majstep = major[1] - major[0]
  97. minor = []
  98. minstep = majstep / (minor_num + 1)
  99. minstart = 0 if self.axis._stop_at_major[0] else -1
  100. minstop = -1 if self.axis._stop_at_major[1] else 0
  101. for i in range(minstart, len(major) + minstop):
  102. maj = major[0] + i * majstep
  103. minor.extend(np.linspace(maj + minstep,
  104. maj + majstep - minstep,
  105. minor_num))
  106. major_frac = (major - offset) / scale
  107. major_frac = major_frac[::-1] if flip else major_frac
  108. use_mask = (major_frac > -0.0001) & (major_frac < 1.0001)
  109. major_frac = major_frac[use_mask]
  110. labels = [l for li, l in enumerate(labels) if use_mask[li]]
  111. minor_frac = (np.array(minor) - offset) / scale
  112. use_minor_mask = (minor_frac > -0.0001) & (minor_frac < 1.0001)
  113. minor_frac = minor_frac[use_minor_mask]
  114. return major_frac, minor_frac, labels
  115. elif self.axis.scale_type == 'logarithmic':
  116. return NotImplementedError
  117. elif self.axis.scale_type == 'power':
  118. return NotImplementedError
  119. Ticker._get_tick_frac_labels = _get_tick_frac_labels