# ########################################################## # FlatCAM: 2D Post-processing for Manufacturing # # http://flatcam.org # # File Author: Dennis Hayrullin # # Date: 2/5/2016 # # MIT Licence # # ########################################################## from vispy.visuals import markers, LineVisual, InfiniteLineVisual from vispy.visuals.axis import Ticker, _get_ticks_talbot from vispy.scene.widgets import Grid import numpy as np def apply_patches(): # Patch MarkersVisual to have crossed lines marker cross_lines = """ float cross(vec2 pointcoord, float size) { //vbar float r1 = abs(pointcoord.x - 0.5)*size; float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2; float vbar = max(r1,r2); //hbar float r3 = abs(pointcoord.y - 0.5)*size; float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2; float hbar = max(r3,r4); return min(vbar, hbar); } """ markers._marker_dict['++'] = cross_lines markers.marker_types = tuple(sorted(list(markers._marker_dict.copy().keys()))) # # Add clear_data method to LineVisual to have possibility of clearing data # def clear_data(self): # self._bounds = None # self._pos = None # self._changed['pos'] = True # self.update() # # LineVisual.clear_data = clear_data # Patch VisPy Grid to prevent updating layout on PaintGL, which cause low fps def _prepare_draw(self, view): pass def _update_clipper(self): super(Grid, self)._update_clipper() try: self._update_child_widget_dim() except Exception as e: print("VisPyPatches.apply_patches._update_clipper() -> %s" % str(e)) Grid._prepare_draw = _prepare_draw Grid._update_clipper = _update_clipper # Patch InfiniteLine visual to 1px width def _prepare_draw(self, view=None): """This method is called immediately before each draw. The *view* argument indicates which view is about to be drawn. """ GL = None from vispy.app._default_app import default_app if default_app is not None and \ default_app.backend_name != 'ipynb_webgl': try: import OpenGL.GL as GL except Exception: # can be other than ImportError sometimes pass if GL: GL.glDisable(GL.GL_LINE_SMOOTH) GL.glLineWidth(2.0) if self._changed['pos']: self.pos_buf.set_data(self._pos) self._changed['pos'] = False if self._changed['color']: self._program.vert['color'] = self._color self._changed['color'] = False InfiniteLineVisual._prepare_draw = _prepare_draw # Patch AxisVisual to have less axis labels def _get_tick_frac_labels(self): """Get the major ticks, minor ticks, and major labels""" minor_num = 4 # number of minor ticks per major division if self.axis.scale_type == 'linear': domain = self.axis.domain if domain[1] < domain[0]: flip = True domain = domain[::-1] else: flip = False offset = domain[0] scale = domain[1] - domain[0] transforms = self.axis.transforms length = self.axis.pos[1] - self.axis.pos[0] # in logical coords n_inches = np.sqrt(np.sum(length ** 2)) / transforms.dpi # major = np.linspace(domain[0], domain[1], num=11) # major = MaxNLocator(10).tick_values(*domain) major = _get_ticks_talbot(domain[0], domain[1], n_inches, 1) labels = ['%g' % x for x in major] majstep = major[1] - major[0] minor = [] minstep = majstep / (minor_num + 1) minstart = 0 if self.axis._stop_at_major[0] else -1 minstop = -1 if self.axis._stop_at_major[1] else 0 for i in range(minstart, len(major) + minstop): maj = major[0] + i * majstep minor.extend(np.linspace(maj + minstep, maj + majstep - minstep, minor_num)) major_frac = (major - offset) / scale major_frac = major_frac[::-1] if flip else major_frac use_mask = (major_frac > -0.0001) & (major_frac < 1.0001) major_frac = major_frac[use_mask] labels = [l for li, l in enumerate(labels) if use_mask[li]] minor_frac = (np.array(minor) - offset) / scale use_minor_mask = (minor_frac > -0.0001) & (minor_frac < 1.0001) minor_frac = minor_frac[use_minor_mask] return major_frac, minor_frac, labels elif self.axis.scale_type == 'logarithmic': return NotImplementedError elif self.axis.scale_type == 'power': return NotImplementedError Ticker._get_tick_frac_labels = _get_tick_frac_labels