示例#1
0
 def reset(self):
     self.matrix = Matrix()
示例#2
0
 def _set_scale(self, scale):
     rescale = scale * 1.0 / self.scale
     self.apply_transform(Matrix().scale(rescale, rescale, rescale),
                          post_multiply=True,
                          anchor=self.to_local(*self.center))
示例#3
0
文件: camera.py 项目: Sires0/Omanut
 def update_projection_matrix(self):
     m = Matrix()
     m.perspective(self.fov * 0.5, self.aspect, self.near, self.far)
     self.projection_matrix = m
    def setInitialZoom(self):
        mat = Matrix().scale(.4, .4, 1)
        self.scatterInstance.apply_transform(mat, (0,0))

        mat = Matrix().translate(200, 100, 0)
        self.scatterInstance.apply_transform(mat)
示例#5
0
class Scatter(Widget):
    '''Scatter class. See module documentation for more information.

    :Events:
        `on_transform_with_touch`:
            Fired when the scatter has been transformed by user touch
            or multitouch, such as panning or zooming.
        `on_bring_to_front`:
            Fired when the scatter is brought to the front.

    .. versionchanged:: 1.9.0
        Event `on_bring_to_front` added.

    .. versionchanged:: 1.8.0
        Event `on_transform_with_touch` added.
    '''

    __events__ = ('on_transform_with_touch', 'on_bring_to_front')

    auto_bring_to_front = BooleanProperty(True)
    '''If True, the widget will be automatically pushed on the top of parent
    widget list for drawing.

    :attr:`auto_bring_to_front` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to True.
    '''

    do_translation_x = BooleanProperty(True)
    '''Allow translation on the X axis.

    :attr:`do_translation_x` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''

    do_translation_y = BooleanProperty(True)
    '''Allow translation on Y axis.

    :attr:`do_translation_y` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''
    def _get_do_translation(self):
        return (self.do_translation_x, self.do_translation_y)

    def _set_do_translation(self, value):
        if type(value) in (list, tuple):
            self.do_translation_x, self.do_translation_y = value
        else:
            self.do_translation_x = self.do_translation_y = bool(value)

    do_translation = AliasProperty(_get_do_translation,
                                   _set_do_translation,
                                   bind=('do_translation_x',
                                         'do_translation_y'))
    '''Allow translation on the X or Y axis.

    :attr:`do_translation` is an :class:`~kivy.properties.AliasProperty` of
    (:attr:`do_translation_x` + :attr:`do_translation_y`)
    '''

    translation_touches = BoundedNumericProperty(1, min=1)
    '''Determine whether translation was triggered by a single or multiple
    touches. This only has effect when :attr:`do_translation` = True.

    :attr:`translation_touches` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 1.

    .. versionadded:: 1.7.0
    '''

    do_rotation = BooleanProperty(True)
    '''Allow rotation.

    :attr:`do_rotation` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''

    do_scale = BooleanProperty(True)
    '''Allow scaling.

    :attr:`do_scale` is a :class:`~kivy.properties.BooleanProperty` and
    defaults to True.
    '''

    do_collide_after_children = BooleanProperty(False)
    '''If True, the collision detection for limiting the touch inside the
    scatter will be done after dispaching the touch to the children.
    You can put children outside the bounding box of the scatter and still be
    able to touch them.

    .. versionadded:: 1.3.0
    '''

    scale_min = NumericProperty(0.01)
    '''Minimum scaling factor allowed.

    :attr:`scale_min` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 0.01.
    '''

    scale_max = NumericProperty(1e20)
    '''Maximum scaling factor allowed.

    :attr:`scale_max` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 1e20.
    '''

    transform = ObjectProperty(Matrix())
    '''Transformation matrix.

    :attr:`transform` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to the identity matrix.

    .. note::

        This matrix reflects the current state of the transformation matrix
        but setting it directly will erase previously applied
        transformations. To apply a transformation considering context,
        please use the :attr:`~Scatter.apply_transform` method.

    '''

    transform_inv = ObjectProperty(Matrix())
    '''Inverse of the transformation matrix.

    :attr:`transform_inv` is an :class:`~kivy.properties.ObjectProperty` and
    defaults to the identity matrix.
    '''

    def _get_bbox(self):
        xmin, ymin = xmax, ymax = self.to_parent(0, 0)
        for point in [(self.width, 0), (0, self.height), self.size]:
            x, y = self.to_parent(*point)
            if x < xmin:
                xmin = x
            if y < ymin:
                ymin = y
            if x > xmax:
                xmax = x
            if y > ymax:
                ymax = y
        return (xmin, ymin), (xmax - xmin, ymax - ymin)

    bbox = AliasProperty(_get_bbox,
                         None,
                         bind=('transform', 'width', 'height'))
    '''Bounding box of the widget in parent space::

        ((x, y), (w, h))
        # x, y = lower left corner

    :attr:`bbox` is an :class:`~kivy.properties.AliasProperty`.
    '''

    def _get_rotation(self):
        v1 = Vector(0, 10)
        tp = self.to_parent
        v2 = Vector(*tp(*self.pos)) - tp(self.x, self.y + 10)
        return -1.0 * (v1.angle(v2) + 180) % 360

    def _set_rotation(self, rotation):
        angle_change = self.rotation - rotation
        r = Matrix().rotate(-radians(angle_change), 0, 0, 1)
        self.apply_transform(r,
                             post_multiply=True,
                             anchor=self.to_local(*self.center))

    rotation = AliasProperty(_get_rotation,
                             _set_rotation,
                             bind=('x', 'y', 'transform'))
    '''Rotation value of the scatter in degrees moving in a counterclockwise
    direction.

    :attr:`rotation` is an :class:`~kivy.properties.AliasProperty` and defaults
    to 0.0.
    '''

    def _get_scale(self):
        p1 = Vector(*self.to_parent(0, 0))
        p2 = Vector(*self.to_parent(1, 0))
        scale = p1.distance(p2)

        # XXX float calculation are not accurate, and then, scale can be
        # throwed again even with only the position change. So to
        # prevent anything wrong with scale, just avoid to dispatch it
        # if the scale "visually" didn't change. #947
        # Remove this ugly hack when we'll be Python 3 only.
        if hasattr(self, '_scale_p'):
            if str(scale) == str(self._scale_p):
                return self._scale_p

        self._scale_p = scale
        return scale

    def _set_scale(self, scale):
        rescale = scale * 1.0 / self.scale
        self.apply_transform(Matrix().scale(rescale, rescale, rescale),
                             post_multiply=True,
                             anchor=self.to_local(*self.center))

    scale = AliasProperty(_get_scale, _set_scale, bind=('x', 'y', 'transform'))
    '''Scale value of the scatter.

    :attr:`scale` is an :class:`~kivy.properties.AliasProperty` and defaults to
    1.0.
    '''

    def _get_center(self):
        return (self.bbox[0][0] + self.bbox[1][0] / 2.0,
                self.bbox[0][1] + self.bbox[1][1] / 2.0)

    def _set_center(self, center):
        if center == self.center:
            return False
        t = Vector(*center) - self.center
        trans = Matrix().translate(t.x, t.y, 0)
        self.apply_transform(trans)

    center = AliasProperty(_get_center, _set_center, bind=('bbox', ))

    def _get_pos(self):
        return self.bbox[0]

    def _set_pos(self, pos):
        _pos = self.bbox[0]
        if pos == _pos:
            return
        t = Vector(*pos) - _pos
        trans = Matrix().translate(t.x, t.y, 0)
        self.apply_transform(trans)

    pos = AliasProperty(_get_pos, _set_pos, bind=('bbox', ))

    def _get_x(self):
        return self.bbox[0][0]

    def _set_x(self, x):
        if x == self.bbox[0][0]:
            return False
        self.pos = (x, self.y)
        return True

    x = AliasProperty(_get_x, _set_x, bind=('bbox', ))

    def _get_y(self):
        return self.bbox[0][1]

    def _set_y(self, y):
        if y == self.bbox[0][1]:
            return False
        self.pos = (self.x, y)
        return True

    y = AliasProperty(_get_y, _set_y, bind=('bbox', ))

    def get_right(self):
        return self.x + self.bbox[1][0]

    def set_right(self, value):
        self.x = value - self.bbox[1][0]

    right = AliasProperty(get_right, set_right, bind=('x', 'width'))

    def get_top(self):
        return self.y + self.bbox[1][1]

    def set_top(self, value):
        self.y = value - self.bbox[1][1]

    top = AliasProperty(get_top, set_top, bind=('y', 'height'))

    def get_center_x(self):
        return self.x + self.bbox[1][0] / 2.

    def set_center_x(self, value):
        self.x = value - self.bbox[1][0] / 2.

    center_x = AliasProperty(get_center_x, set_center_x, bind=('x', 'width'))

    def get_center_y(self):
        return self.y + self.bbox[1][1] / 2.

    def set_center_y(self, value):
        self.y = value - self.bbox[1][1] / 2.

    center_y = AliasProperty(get_center_y, set_center_y, bind=('y', 'height'))

    def __init__(self, **kwargs):
        self._touches = []
        self._last_touch_pos = {}
        super(Scatter, self).__init__(**kwargs)

    def on_transform(self, instance, value):
        self.transform_inv = value.inverse()

    def collide_point(self, x, y):
        x, y = self.to_local(x, y)
        return 0 <= x <= self.width and 0 <= y <= self.height

    def to_parent(self, x, y, **k):
        p = self.transform.transform_point(x, y, 0)
        return (p[0], p[1])

    def to_local(self, x, y, **k):
        p = self.transform_inv.transform_point(x, y, 0)
        return (p[0], p[1])

    def _apply_transform(self, m, pos=None):
        m = self.transform.multiply(m)
        return super(Scatter, self)._apply_transform(m, (0, 0))

    def apply_transform(self, trans, post_multiply=False, anchor=(0, 0)):
        '''
        Transforms the scatter by applying the "trans" transformation
        matrix (on top of its current transformation state). The resultant
        matrix can be found in the :attr:`~Scatter.transform` property.

        :Parameters:
            `trans`: :class:`~kivy.graphics.transformation.Matrix`.
                Transformation matix to be applied to the scatter widget.
            `anchor`: tuple, defaults to (0, 0).
                The point to use as the origin of the transformation
                (uses local widget space).
            `post_multiply`: bool, defaults to False.
                If True, the transform matrix is post multiplied
                (as if applied before the current transform).

        Usage example::

            from kivy.graphics.transformation import Matrix
            mat = Matrix().scale(3, 3, 3)
            scatter_instance.apply_transform(mat)

        '''
        t = Matrix().translate(anchor[0], anchor[1], 0)
        t = t.multiply(trans)
        t = t.multiply(Matrix().translate(-anchor[0], -anchor[1], 0))

        if post_multiply:
            self.transform = self.transform.multiply(t)
        else:
            self.transform = t.multiply(self.transform)

    def transform_with_touch(self, touch):
        # just do a simple one finger drag
        changed = False
        if len(self._touches) == self.translation_touches:
            # _last_touch_pos has last pos in correct parent space,
            # just like incoming touch
            dx = (touch.x - self._last_touch_pos[touch][0]) \
                * self.do_translation_x
            dy = (touch.y - self._last_touch_pos[touch][1]) \
                * self.do_translation_y
            dx = dx / self.translation_touches
            dy = dy / self.translation_touches
            self.apply_transform(Matrix().translate(dx, dy, 0))
            changed = True

        if len(self._touches) == 1:
            return changed

        # we have more than one touch... list of last known pos
        points = [
            Vector(self._last_touch_pos[t]) for t in self._touches
            if t is not touch
        ]
        # add current touch last
        points.append(Vector(touch.pos))

        # we only want to transform if the touch is part of the two touches
        # farthest apart! So first we find anchor, the point to transform
        # around as another touch farthest away from current touch's pos
        anchor = max(points[:-1], key=lambda p: p.distance(touch.pos))

        # now we find the touch farthest away from anchor, if its not the
        # same as touch. Touch is not one of the two touches used to transform
        farthest = max(points, key=anchor.distance)
        if farthest is not points[-1]:
            return changed

        # ok, so we have touch, and anchor, so we can actually compute the
        # transformation
        old_line = Vector(*touch.ppos) - anchor
        new_line = Vector(*touch.pos) - anchor
        if not old_line.length():  # div by zero
            return changed

        angle = radians(new_line.angle(old_line)) * self.do_rotation
        self.apply_transform(Matrix().rotate(angle, 0, 0, 1), anchor=anchor)

        if self.do_scale:
            scale = new_line.length() / old_line.length()
            new_scale = scale * self.scale
            if new_scale < self.scale_min:
                scale = self.scale_min / self.scale
            elif new_scale > self.scale_max:
                scale = self.scale_max / self.scale
            self.apply_transform(Matrix().scale(scale, scale, scale),
                                 anchor=anchor)
            changed = True
        return changed

    def _bring_to_front(self, touch):
        # auto bring to front
        if self.auto_bring_to_front and self.parent:
            parent = self.parent
            if parent.children[0] is self:
                return
            parent.remove_widget(self)
            parent.add_widget(self)
            self.dispatch('on_bring_to_front', touch)

    def on_touch_down(self, touch):
        x, y = touch.x, touch.y

        # if the touch isnt on the widget we do nothing
        if not self.do_collide_after_children:
            if not self.collide_point(x, y):
                return False

        # let the child widgets handle the event if they want
        touch.push()
        touch.apply_transform_2d(self.to_local)
        if super(Scatter, self).on_touch_down(touch):
            # ensure children don't have to do it themselves
            if 'multitouch_sim' in touch.profile:
                touch.multitouch_sim = True
            touch.pop()
            self._bring_to_front(touch)
            return True
        touch.pop()

        # if our child didn't do anything, and if we don't have any active
        # interaction control, then don't accept the touch.
        if not self.do_translation_x and \
                not self.do_translation_y and \
                not self.do_rotation and \
                not self.do_scale:
            return False

        if self.do_collide_after_children:
            if not self.collide_point(x, y):
                return False

        if 'multitouch_sim' in touch.profile:
            touch.multitouch_sim = True
        # grab the touch so we get all it later move events for sure
        self._bring_to_front(touch)
        touch.grab(self)
        self._touches.append(touch)
        self._last_touch_pos[touch] = touch.pos

        return True

    def on_touch_move(self, touch):
        x, y = touch.x, touch.y
        # let the child widgets handle the event if they want
        if self.collide_point(x, y) and not touch.grab_current == self:
            touch.push()
            touch.apply_transform_2d(self.to_local)
            if super(Scatter, self).on_touch_move(touch):
                touch.pop()
                return True
            touch.pop()

        # rotate/scale/translate
        if touch in self._touches and touch.grab_current == self:
            if self.transform_with_touch(touch):
                self.dispatch('on_transform_with_touch', touch)
            self._last_touch_pos[touch] = touch.pos

        # stop propagating if its within our bounds
        if self.collide_point(x, y):
            return True

    def on_transform_with_touch(self, touch):
        '''
        Called when a touch event has transformed the scatter widget.
        By default this does nothing, but can be overriden by derived
        classes that need to react to transformations caused by user
        input.

        :Parameters:
            `touch`:
                The touch object which triggered the transformation.

        .. versionadded:: 1.8.0
        '''
        pass

    def on_bring_to_front(self, touch):
        '''
        Called when a touch event causes the scatter to be brought to the
        front of the parent (only if :attr:`auto_bring_to_front` is True)

        :Parameters:
            `touch`:
                The touch object which brought the scatter to front.

        .. versionadded:: 1.9.0
        '''
        pass

    def on_touch_up(self, touch):
        x, y = touch.x, touch.y
        # if the touch isnt on the widget we do nothing, just try children
        if not touch.grab_current == self:
            touch.push()
            touch.apply_transform_2d(self.to_local)
            if super(Scatter, self).on_touch_up(touch):
                touch.pop()
                return True
            touch.pop()

        # remove it from our saved touches
        if touch in self._touches and touch.grab_state:
            touch.ungrab(self)
            del self._last_touch_pos[touch]
            self._touches.remove(touch)

        # stop propagating if its within our bounds
        if self.collide_point(x, y):
            return True
示例#6
0
class RotateLabel(Label):

    transform = ObjectProperty(Matrix())
示例#7
0
    def transform_with_touch(self, touch):
        # just do a simple one finger drag
        changed = False
        if len(self._touches) == self.translation_touches:
            # _last_touch_pos has last pos in correct parent space,
            # just like incoming touch
            dx = (touch.x -
                  self._last_touch_pos[touch][0]) * self.do_translation_x
            dy = (touch.y -
                  self._last_touch_pos[touch][1]) * self.do_translation_y
            dx = dx / self.translation_touches
            dy = dy / self.translation_touches
            m = Matrix().translate(dx, dy, 0)
            if self.check_trans(m):
                self.apply_transform(Matrix().translate(dx, dy, 0))
                changed = True
            else:
                pass

        if len(self._touches) == 1:
            return changed

        # we have more than one touch... list of last known pos
        points = [
            Vector(self._last_touch_pos[t]) for t in self._touches
            if t is not touch
        ]
        # add current touch last
        points.append(Vector(touch.pos))

        # we only want to transform if the touch is part of the two touches
        # farthest apart! So first we find anchor, the point to transform
        # around as another touch farthest away from current touch's pos
        anchor = max(points[:-1], key=lambda p: p.distance(touch.pos))

        # now we find the touch farthest away from anchor, if its not the
        # same as touch. Touch is not one of the two touches used to transform
        farthest = max(points, key=anchor.distance)
        if farthest is not points[-1]:
            return changed

        # ok, so we have touch, and anchor, so we can actually compute the
        # transformation
        old_line = Vector(*touch.ppos) - anchor
        new_line = Vector(*touch.pos) - anchor
        if not old_line.length():  # div by zero
            return changed

        angle = radians(new_line.angle(old_line)) * self.do_rotation
        self.apply_transform(Matrix().rotate(angle, 0, 0, 1), anchor=anchor)

        if self.do_scale:
            scale = new_line.length() / old_line.length()
            new_scale = scale * self.scale
            if new_scale < self.scale_min:
                scale = self.scale_min / self.scale
            elif new_scale > self.scale_max:
                scale = self.scale_max / self.scale
            m = Matrix().scale(scale, scale, scale)
            if self.check_trans(m):
                self.apply_transform(Matrix().scale(scale, scale, scale),
                                     anchor=anchor)
                changed = True
            else:
                pass
        return changed
示例#8
0
 def _update_glsl(self):
     asp = self.width / float(self.height)
     proj = Matrix().view_clip(-asp, asp, -1, 1, 1.5, 100, 1)
     self.canvas["projection_mat"] = proj
示例#9
0
 def on_bypass(self, instance, bypass):
     if bypass:
         self.transform = Matrix()
示例#10
0
 def update_glsl(self, *args):
     asp = self.width / max(float(self.height), 1)
     proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
     self.fbo['projection_mat'] = proj
示例#11
0
    def __init__(self, **kw):

        self.cube_vertices = []

        cube = np.zeros((8, 3), 'f')
        i = 0
        for x in (-1, 1):
            for y in (-1, 1):
                for z in (-1, 1):
                    cube[i] = [x, y, z]
                    i += 1

        # Shift the cube down below the x-axis
        cube[:, 0:1] -= 1
        cube[:, 1:2] += 1
        cube[:, 2:3] -= 1

        # Create cubes for each position
        for x in (-2, 0, 2):
            c = cube.copy()
            c[:, 0:1] += x
            self.cube_vertices.append(c.flatten())

            for y in (0, 2, 4):
                d = c.copy()
                d[:, 1:2] += y
                self.cube_vertices.append(d.flatten())

                for z in (0, -2, -4):
                    e = d.copy()
                    e[:, 2:3] += z
                    self.cube_vertices.append(e.flatten())

        # The indices for each cube
        self.cube_indices = [
            0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 3, 2, 3, 7, 2, 6, 6, 7, 7, 5, 6, 4,
            4, 5
        ]

        self.line_vertices = np.array(
            [[0.000000, 0.000000, -0.000000], [0.000000, 1, -1.0],
             [0.000000, 2, -2.0], [0.000000, 3, -3.0], [0.000000, 4, -4.0],
             [0.000000, 5, -5.0], [0.000000, 6, -6.0], [0.000000, 7, -7.0],
             [0.000000, 8, -8.0], [0.000000, 9, -9.0], [0.000000, 10, -10.0],
             [0.000000, 11, -10.0], [0.000000, 12, -10.0], [
                 0.000000, 13, -10.0
             ], [0.000000, 14, -10.0], [5.000000, 15, -10.0],
             [5.000000, 16, -10.0], [5.000000, 17, -10.0],
             [5.000000, 18, -10.0], [5.000000, 19, -10.0], [
                 5.000000, 20, -10.0
             ], [5.000000, 21, -10.0], [5.000000, 22, -10.0],
             [5.000000, 23, -10.0], [5.000000, 24, -15.0], [
                 5.000000, 25, -15.0
             ], [5.000000, 26, -15.0], [5.000000, 27, -15.0],
             [5.000000, 28, -15.0], [0.000000, 29, -15.0], [
                 0.000000, 30, -15.0
             ], [0.000000, 31, -15.0], [0.000000, 32, -15.0],
             [0.000000, 33, -15.0], [0.000000, 34, -15.0], [
                 0.000000, 35, -15.0
             ], [0.000000, 36, -15.0], [0.000000, 37, -15.0],
             [0.000000, 38, -15.0], [0.000000, 39, -15.0], [
                 0.000000, 40, -15.0
             ], [0.000000, 41, -30.0], [0.000000, 42, -30.0],
             [0.000000, 43, -30.0], [0.000000, 44, -30.0], [
                 0.000000, 45, -30.0
             ], [0.000000, 46, -30.0], [0.000000, 47, -30.0],
             [0.000000, 48, -30.0], [0.000000, 49, -30.0], [
                 0.000000, 50, -30.0
             ], [0.000000, 51, -30.0], [0.000000, 52, -30.0],
             [0.000000, 53, -30.0], [0.000000, 54, -30.0], [
                 0.000000, 55, -30.0
             ], [0.000000, 56, -30.0], [0.000000, 57, -30.0],
             [0.000000, 58, -30.0], [0.000000, 59, -30.0]], 'f')

        #self.line_vertices = np.array( [ [ 0.000000, 0.000000, 0.000000 ],
        #		       	         [ 0.000000, 0.999998, -0.001745 ],
        #		       	         [ 0.000000, 1.999997, -0.003491 ],
        #		       	         [ 0.000000, 2.999995, -0.005236 ],
        #		       	         [ 0.000000, 3.999994, -0.006981 ],
        #		       	         [ 0.000000, 4.999992, -0.008727 ],
        #		       	         [ 0.000000, 5.999991, -0.010472 ],
        #		       	         [ 0.000000, 6.999989, -0.012217 ],
        #		       	         [ 0.000000, 7.999988, -0.013963 ],
        #		       	         [ 0.000000, 8.999986, -0.015708 ],
        #		       	         [ 0.000000, 9.999985, -0.017453 ],
        #		       	         [ 0.000000, 10.999983, -0.019199 ],
        #		       	         [ 0.000000, 11.999982, -0.020944 ],
        #		       	         [ 0.000000, 12.999980, -0.022689 ],
        #		       	         [ 0.000000, 13.999979, -0.024435 ],
        #		       	         [ 0.000000, 14.999977, -0.026180 ],
        #		       	         [ 0.000000, 15.999976, -0.027925 ],
        #		       	         [ 0.000000, 16.999974, -0.029671 ],
        #		       	         [ 0.000000, 17.999973, -0.031416 ],
        #		       	         [ 0.000000, 18.999971, -0.033161 ],
        #		       	         [ 0.000000, 19.999970, -0.034907 ],
        #		       	         [ 0.000000, 20.999968, -0.036652 ],
        #		       	         [ 0.000000, 21.999966, -0.038397 ],
        #		       	         [ 0.000000, 22.999965, -0.040143 ],
        #		       	         [ 0.000000, 23.999963, -0.041888 ],
        #		       	         [ 0.000000, 24.999962, -0.043633 ],
        #		       	         [ 0.000000, 25.999960, -0.045379 ],
        #		       	         [ 0.000000, 26.999959, -0.047124 ],
        #		       	         [ 0.000000, 27.999957, -0.048869 ],
        #		       	         [ 0.000000, 28.999956, -0.050615 ],
        #		       	         [ 0.000000, 29.999954, -0.052360 ],
        #		       	         [ 0.000000, 30.999953, -0.054105 ],
        #		       	         [ 0.000000, 31.999951, -0.055851 ],
        #		       	         [ 0.000000, 32.999950, -0.057596 ],
        #		       	         [ 0.000000, 33.999948, -0.059341 ],
        #		       	         [ 0.000000, 34.999947, -0.061086 ],
        #		       	         [ 0.000000, 35.999945, -0.062832 ],
        #		       	         [ 0.000000, 36.999944, -0.064577 ],
        #		       	         [ 0.000000, 37.999942, -0.066322 ],
        #		       	         [ 0.000000, 38.999941, -0.068068 ],
        #		       	         [ 0.000000, 39.999939, -0.069813 ],
        #		       	         [ 0.000000, 40.999938, -0.071558 ],
        #		       	         [ 0.000000, 41.999936, -0.073304 ],
        #		       	         [ 0.000000, 42.999935, -0.075049 ],
        #		       	         [ 0.000000, 43.999933, -0.076794 ],
        #		       	         [ 0.000000, 44.999931, -0.078540 ],
        #		       	         [ 0.000000, 45.999930, -0.080285 ],
        #		       	         [ 0.000000, 46.999928, -0.082030 ],
        #		       	         [ 0.000000, 47.999927, -0.083776 ],
        #		       	         [ 0.000000, 48.999925, -0.085521 ],
        #		       	         [ 0.000000, 49.999924, -0.087266 ],
        #		       	         [ 0.000000, 50.999922, -0.089012 ],
        #		       	         [ 0.000000, 51.999921, -0.090757 ],
        #		       	         [ 0.000000, 52.999919, -0.092502 ],
        #		       	         [ 0.000000, 53.999918, -0.094248 ],
        #		       	         [ 0.000000, 54.999916, -0.095993 ],
        #		       	         [ 0.000000, 55.999915, -0.097738 ],
        #		       	         [ 0.000000, 56.999913, -0.099484 ],
        #		       	         [ 0.000000, 57.999912, -0.101229 ],
        #		       	         [ 0.000000, 58.999910, -0.102974 ],
        #		       	         [ 0.000000, 59.999909, -0.104720 ],
        #		       	         [ 0.000000, 60.999907, -0.106465 ],
        #		       	         [ 0.000000, 61.999906, -0.108210 ],
        #		       	         [ 0.000000, 62.999904, -0.109956 ],
        #		       	         [ 0.000000, 63.999903, -0.111701 ],
        #		       	         [ 0.000000, 64.999901, -0.113446 ],
        #		       	         [ 0.000000, 65.999899, -0.115192 ],
        #		       	         [ 0.000000, 66.999898, -0.116937 ],
        #		       	         [ 0.000000, 67.999896, -0.118682 ],
        #		       	         [ 0.000000, 68.999895, -0.120428 ],
        #		       	         [ 0.000000, 69.999893, -0.122173 ],
        #		       	         [ 0.000000, 70.999892, -0.123918 ],
        #		       	         [ 0.000000, 71.999890, -0.125664 ],
        #		       	         [ 0.000000, 72.999889, -0.127409 ],
        #		       	         [ 0.000000, 73.999887, -0.129154 ],
        #		       	         [ 0.000000, 74.999886, -0.130900 ],
        #		       	         [ 0.000000, 75.999884, -0.132645 ],
        #		       	         [ 0.000000, 76.999883, -0.134390 ],
        #		       	         [ 0.000000, 77.999881, -0.136136 ],
        #		       	         [ 0.000000, 78.999880, -0.137881 ],
        #		       	         [ 0.000000, 79.999878, -0.139626 ],
        #		       	         [ 0.000000, 80.999877, -0.141372 ],
        #		       	         [ 0.000000, 81.999875, -0.143117 ],
        #		       	         [ 0.000000, 82.999874, -0.144862 ],
        #		       	         [ 0.000000, 83.999872, -0.146608 ],
        #		       	         [ 0.000000, 84.999871, -0.148353 ],
        #		       	         [ 0.000000, 85.999869, -0.150098 ],
        #		       	         [ 0.000000, 86.999867, -0.151844 ],
        #		       	         [ 0.000000, 87.999866, -0.153589 ],
        #		       	         [ 0.000000, 88.999864, -0.155334 ],
        #		       	         [ 0.000000, 89.999863, -0.157080 ],
        #		       	         [ 0.000000, 90.999861, -0.158825 ],
        #		       	         [ 0.000000, 91.999860, -0.160570 ],
        #		       	         [ 0.000000, 92.999858, -0.162316 ],
        #		       	         [ 0.000000, 93.999857, -0.164061 ],
        #		       	         [ 0.000000, 94.999855, -0.165806 ],
        #		       	         [ 0.000000, 95.999854, -0.167552 ],
        #		       	         [ 0.000000, 96.999852, -0.169297 ],
        #		       	         [ 0.000000, 97.999851, -0.171042 ],
        #		       	         [ 0.000000, 98.999849, -0.172788 ],
        #		       	         [ 0.000000, 99.999848, -0.174533 ],
        #		       	         [ 0.000000, 100.999846, -0.176278 ],
        #		       	         [ 0.000000, 101.999845, -0.178023 ],
        #		       	         [ 0.000000, 102.999843, -0.179769 ],
        #		       	         [ 0.000000, 103.999842, -0.181514 ],
        #		       	         [ 0.000000, 104.999840, -0.183259 ],
        #		       	         [ 0.000000, 105.999839, -0.185005 ],
        #		       	         [ 0.000000, 106.999837, -0.186750 ],
        #		       	         [ 0.000000, 107.999836, -0.188495 ],
        #		       	         [ 0.000000, 108.999834, -0.190241 ],
        #		       	         [ 0.000000, 109.999832, -0.191986 ],
        #		       	         [ 0.000000, 110.999831, -0.193731 ],
        #		       	         [ 0.000000, 111.999829, -0.195477 ],
        #		       	         [ 0.000000, 112.999828, -0.197222 ],
        #		       	         [ 0.000000, 113.999826, -0.198967 ],
        #		       	         [ 0.000000, 114.999825, -0.200713 ],
        #		       	         [ 0.000000, 115.999823, -0.202458 ],
        #		       	         [ 0.000000, 116.999822, -0.204203 ],
        #		       	         [ 0.000000, 117.999820, -0.205949 ],
        #		       	         [ 0.000000, 118.999819, -0.207694 ],
        #		       	         [ 0.000000, 119.999817, -0.209439 ],
        #		       	         [ 0.000000, 120.999816, -0.211185 ],
        #		       	         [ 0.000000, 121.999814, -0.212930 ],
        #		       	         [ 0.000000, 122.999813, -0.214675 ] ], 'f' )

        self.line_indices = []
        for i in range(0, int(len(self.line_vertices) / 3)):
            self.line_indices += [i, i + 1]

        kw['shader_file'] = 'shaders.glsl'
        self.canvas = RenderContext(compute_normal_mat=True)
        shader_file = kw.pop('shader_file')
        self.canvas.shader.source = resource_find(shader_file)
        self._touches = []

        super(Renderer, self).__init__(**kw)

        with self.canvas:
            # This controls the camera position, or rather, shifts the world
            Translate(0, -1, -15)

            self.rot = Rotate(0, 1, 1, 1)
            self.rotx = Rotate(0, 1, 0, 0)
            self.roty = Rotate(0, 0, 1, 0)

            # This controls the zoom
            self.scale = Scale(1)

            # Change the colour of the mesh to red.
            ChangeState(Kd=(1.0, 0.0, 0.0),
                        Ka=(1.0, 1.0, 0.0),
                        Ks=(.3, .3, .3),
                        Tr=1.,
                        Ns=1.,
                        intensity=0.5)

            # Draw the vertices and indices
            for i in range(len(self.cube_vertices)):
                Mesh(vertices=self.cube_vertices[i],
                     indices=self.cube_indices,
                     fmt=[(b'v_pos', 3, 'float')],
                     mode='lines')

            # Change the details of the line, i.e. colour to green
            ChangeState(Kd=(0.0, 1.0, 0.0),
                        Ka=(1.0, 1.0, 0.0),
                        Ks=(.3, .3, .3),
                        Tr=1.,
                        Ns=1.,
                        intensity=1.)

            # Draw the line
            self.bh_line = Mesh(vertices=self.line_vertices.flatten(),
                                indices=self.line_indices,
                                fmt=[(b'v_pos', 3, 'float')],
                                mode='lines')

            print(self.bh_line.indices)

        asp = float(Window.width) / Window.height / 2.0
        proj = Matrix().view_clip(-asp, asp, -0.5, 0.5, 1, 100, 1)
        self.canvas['projection_mat'] = proj

        Window.request_keyboard(None,
                                self).bind(on_key_down=self.on_keyboard_down)
示例#12
0
 def on_scale(self, instance, scale):
     matrix = Matrix()
     matrix.scale(scale, scale, 1)
     matrix.translate((-scale + 1) * 0.5 * self.width, -scale * self.height / 4, 0)
     self.instruction.matrix = matrix
示例#13
0
class ImageWidget(BoxLayout):
    orientation = 'vertical'
    imageList = None
    coreImage = None
    currentPos = 0
    imageAngle = NumericProperty(0)
    imageScale = NumericProperty(1)
    imageNumber = StringProperty("")
    imageName = StringProperty("")
    imageLoader = ImageLoader(threads=4)

    reflect = Matrix().scale(0.1, 1, 1)
    buttonSchedule = None

    def __init__(self, onClick=None, **kwargs):
        tmp = os.getcwd()
        os.chdir('ui')
        Builder.load_file('imagewidget.kv')
        super().__init__(**kwargs)
        self.id = 'image'
        self.onClick = onClick
        os.chdir(tmp)

    def setImageList(self, imageList):
        self.imageList = imageList
        self.currentPos = 0
        self.imageLoader.loadImageList(imageList)
        self.openImage(self.imageList[self.currentPos][3], self.currentPos)
        self.imageName = self.imageList[self.currentPos][4]
        self.imageNumber = "{}/{}".format(self.currentPos + 1,
                                          len(self.imageList))

    def on_left_press(self, step=0):
        if self.imageList is not None:
            amount = 1
            if step > 0:
                amount = int(len(self.imageList) * step / 100.0)
            self.currentPos -= max(amount, 1)
            if self.currentPos < 0:
                self.currentPos = 0
            if self.buttonSchedule is not None:
                Clock.unschedule(self.buttonSchedule)
                self.buttonSchedule = None
            self.buttonSchedule = Clock.schedule_once(
                partial(self.openPicture, self.currentPos), 0.1)
            self.imageNumber = "{}/{}".format(self.currentPos + 1,
                                              len(self.imageList))
            self.imageName = self.imageList[self.currentPos][4]

    def on_right_press(self, step=0):
        if self.imageList is not None:
            amount = 1
            if step > 0:
                amount = int(len(self.imageList) * step / 100.0)
            self.currentPos += max(amount, 1)
            if self.currentPos >= len(self.imageList):
                self.currentPos = len(self.imageList) - 1
            if self.buttonSchedule is not None:
                Clock.unschedule(self.buttonSchedule)
                self.buttonSchedule = None
            self.buttonSchedule = Clock.schedule_once(
                partial(self.openPicture, self.currentPos), 0.1)
            self.imageNumber = "{}/{}".format(self.currentPos + 1,
                                              len(self.imageList))
            self.imageName = self.imageList[self.currentPos][4]

    def openPicture(self, *args):
        pos = args[0]
        if pos != self.currentPos:
            return
        self.openImage(self.imageList[self.currentPos][3], self.currentPos)

    def reTryOpen(self, *largs):
        pos = largs[0]
        name = largs[1]
        self.openImage(name, pos)

    def openImage(self, name, pos):
        print(name)
        image = self.imageLoader.getImage(pos)
        if image['status'] != 'loaded':
            print("waiting")
            Clock.schedule_once(partial(self.reTryOpen, pos, name), 0.5)

        else:
            imData = image
            tex = self.get_texture(imData)
            self.ids.image.texture = tex
            if imData['vflip']:
                self.ids.image.texture.flip_vertical()
            if imData['hflip']:
                self.ids.image.texture.flip_horizontal()
            self.imageAngle = imData['angle']
            if self.imageAngle % 180 != 0:
                self.imageScale = self.height / self.width
            else:
                self.imageScale = 1

    def get_texture(self, data):
        bt = data['image']
        full: PillowImage = PillowImage.open(io.BytesIO(bt))
        exif_data = full._getexif()
        angle = 0
        vFlip = True
        hFlip = False
        # is there a rotation?
        rotation = 1
        if exif_data is not None and 274 in exif_data:
            rotation = exif_data[274]
        if rotation == 1:
            full = full.transpose(PillowImage.FLIP_LEFT_RIGHT)
        if rotation == 2:
            full = full.transpose(PillowImage.FLIP_LEFT_RIGHT)
        elif rotation == 3:
            full = full.transpose(PillowImage.ROTATE_180)
        elif rotation == 4:
            pass
        elif rotation == 5:
            full = full.transpose(PillowImage.FLIP_LEFT_RIGHT).transpose(
                PillowImage.ROTATE_270)  #swap 90 and 270
        elif rotation == 6:
            full = full.transpose(PillowImage.FLIP_LEFT_RIGHT).transpose(
                PillowImage.ROTATE_90)  #here too
        elif rotation == 7:
            full = full.transpose(PillowImage.ROTATE_90)
        elif rotation == 8:
            full = full.transpose(PillowImage.FLIP_LEFT_RIGHT).transpose(
                PillowImage.ROTATE_270)
        coreImage = CoreImageData(full.size[0], full.size[1],
                                  full.mode.lower(), full.tobytes())
        texture = Texture.create_from_data(coreImage)
        data['angle'] = angle
        data['vflip'] = vFlip
        data['hflip'] = not hFlip
        return texture
示例#14
0
文件: main.py 项目: gitbork/pi-scan
 def moveRight(self):
   try:
     self.scatter.apply_transform(Matrix().translate(x=-100/self.scatter.scale,y=0,z=0))
   except Exception as e:
     handleCrash(e)
示例#15
0
    def update_glsl(self, *largs):
        width = self.width if self.width > 1 else 100
        height = self.height if self.height > 1 else 100

        asp = width / float(height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 600, 1)
        proj = Matrix()
        proj.perspective(self.perspective_value, asp, 1, 1000)

        matrix_camera = Matrix().identity()
        matrix_camera = matrix_camera.look_at(*self.look_at)

        self.canvas['projection_mat'] = proj
        self.canvas['camera'] = matrix_camera

        self.canvas['diffuse_light'] = (0.0, 1.0, 0.0)
        self.canvas['ambient_light'] = [v for v in self.ambient_light]
        self.canvas['light_visibility'] = self.light_intensity
        self.canvas['eye_position'] = [self.look_at[0], self.look_at[1], self.look_at[2]]
        self.canvas['light_position'] = [self.light_position[0], self.light_position[1],
                                         self.light_position[2]]

        self.canvas['light_orientation'] = [self.light_orientation[0], self.light_orientation[1],
                                            self.light_orientation[2]]
        self.canvas['light_0'] = [self.light_0[0], self.light_0[1],
                                            self.light_0[2]]
        self.canvas['light_1'] = [self.light_1[0], self.light_1[1],
                                            self.light_1[2]]

        if self.shadow:
            self.canvas['texture1'] = 1
            self.canvas['texture2'] = 2
            self.canvas["enabled_shadow"] = 1.0
        else:

            self.canvas["enabled_shadow"] = 0.0
            self.canvas["texture1"] = 0

        depthProjectionMatrix = Matrix().view_clip(-100 * self.shadow_threshold, 100 * self.shadow_threshold,
                                                   -100 * self.shadow_threshold, 100 * self.shadow_threshold,
                                                   -100 * self.shadow_threshold, 200 * self.shadow_threshold * 2, 0)
        _shadow_pos = self._shadow_pos
        _shadow_target = self._shadow_target
        depthViewMatrix = Matrix().look_at(_shadow_target[0], _shadow_target[1],
                                           _shadow_target[2] + self._shadow_offset,
                                           _shadow_pos[0], _shadow_pos[1], _shadow_pos[2], 0, 1, 0)

        depthModelMatrix = Matrix().identity()
        depthMVP = depthProjectionMatrix.multiply(depthViewMatrix).multiply(depthModelMatrix)
        self.canvas['depthMVP'] = depthMVP
        self.canvas['cond'] = (0.0, 0.7)
        self.canvas['val_sin'] = (self.alpha, 0.0)

        if self.shadow:
            self.update_fbo(largs[0])
            # label.text = str(Clock.get_rfps())

        if self.parent.parent is None:
            # del self.parent

            self.parent.canvas3d = None
            self.fbo_list.clear()
            self.fbo = None
            for a in self.nodes:
                a.remove_a()
            self.nodes = []
            self.parent._nodes = []
            self.parent.clear_widgets()
            self.adding_queue = []
            self.nt.cancel()
示例#16
0
    def update_img(self, img, force=False):
        ''' Updates the screen with a new image.

        :Parameters:

            `img`: :class:`~ffpyplayer.pic.Image` instance
                The image to be displayed.
        '''
        from ffpyplayer.tools import get_best_pix_fmt
        from ffpyplayer.pic import SWScale
        if img is None:
            return

        img_fmt = img.get_pixel_format()
        self.image_size = img_w, img_h = img.get_size()

        update = force
        if self._iw != img_w or self._ih != img_h:
            update = True

        if img_fmt not in ('yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra'):
            swscale = self._swscale
            if img_fmt != self._sw_src_fmt or swscale is None or update:
                ofmt = get_best_pix_fmt(
                    img_fmt, (
                        'yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra'))
                self._swscale = swscale = SWScale(
                    iw=img_w, ih=img_h, ifmt=img_fmt, ow=0, oh=0, ofmt=ofmt)
                self._sw_src_fmt = img_fmt
            img = swscale.scale(img)
            img_fmt = img.get_pixel_format()

        w, h = self.available_size or self.size
        if (not w) or not h:
            self.img = img
            return

        if self._fmt != img_fmt:
            self._fmt = img_fmt
            self._kivy_ofmt = {
                'yuv420p': 'yuv420p', 'rgba': 'rgba', 'rgb24': 'rgb',
                'gray': 'luminance', 'bgr24': 'bgr', 'bgra': 'bgra'}[img_fmt]
            update = True

        if update or w != self._last_w or h != self._last_h or \
                self.rotation != self._last_rotation:
            if self.scale_to_image:
                rotation = self.rotation
                rot = self.rotation * math.pi / 180
                rot_w = abs(img_w * math.cos(rot)) + abs(img_h * math.sin(rot))
                rot_h = abs(img_h * math.cos(rot)) + abs(img_w * math.sin(rot))
                scalew, scaleh = w / rot_w, h / rot_h
                scale = min(min(scalew, scaleh), 1)
                self.transform = Matrix()
                self.rotation = rotation
                self.apply_transform(Matrix().scale(scale, scale, 1),
                                     post_multiply=True)
                self.pos = 0, 0
            self._iw, self._ih = img_w, img_h
            self._last_h = h
            self._last_w = w
            self._last_rotation = self.rotation

        self.img = img
        kivy_ofmt = self._kivy_ofmt

        if update:
            self.canvas.remove_group(str(self) + 'image_display')
            if kivy_ofmt == 'yuv420p':
                w2 = int(img_w / 2)
                h2 = int(img_h / 2)
                self._tex_y = Texture.create(size=(img_w, img_h),
                                             colorfmt='luminance')
                self._tex_u = Texture.create(size=(w2, h2),
                                             colorfmt='luminance')
                self._tex_v = Texture.create(size=(w2, h2),
                                             colorfmt='luminance')
                with self.canvas:
                    self._fbo = fbo = Fbo(size=(img_w, img_h),
                                          group=str(self) + 'image_display')
                with fbo:
                    BindTexture(texture=self._tex_u, index=1)
                    BindTexture(texture=self._tex_v, index=2)
                    Rectangle(size=fbo.size, texture=self._tex_y)
                fbo.shader.fs = BufferImage._YUV_RGB_FS
                fbo['tex_y'] = 0
                fbo['tex_u'] = 1
                fbo['tex_v'] = 2
                tex = self.img_texture = fbo.texture
                fbo.add_reload_observer(self.reload_buffer)
            else:
                tex = self.img_texture = Texture.create(
                    size=(img_w, img_h), colorfmt=kivy_ofmt)
                tex.add_reload_observer(self.reload_buffer)

            tex.flip_vertical()
            if self.flip:
                tex.flip_horizontal()
            self.texture_size = img_w, img_h

        if kivy_ofmt == 'yuv420p':
            dy, du, dv, _ = img.to_memoryview()
            self._tex_y.blit_buffer(dy, colorfmt='luminance')
            self._tex_u.blit_buffer(du, colorfmt='luminance')
            self._tex_v.blit_buffer(dv, colorfmt='luminance')
            self._fbo.ask_update()
            self._fbo.draw()
        else:
            self.img_texture.blit_buffer(img.to_memoryview()[0],
                                         colorfmt=kivy_ofmt)
            self.canvas.ask_update()
示例#17
0
 def _update_labels(self):
     xlabel = self._xlabel
     ylabel = self._ylabel
     x = self.x
     y = self.y
     width = self.width
     height = self.height
     padding = self.padding
     x_next = padding + x
     y_next = padding + y
     xextent = width + x
     yextent = height + y
     ymin = self.ymin
     ymax = self.ymax
     xmin = self.xmin
     precision = self.precision
     x_overlap = False
     y_overlap = False
     # set up x and y axis labels
     if xlabel:
         xlabel.text = self.xlabel
         xlabel.texture_update()
         xlabel.size = xlabel.texture_size
         xlabel.pos = int(x + width / 2. - xlabel.width / 2.), int(padding +
                                                                   y)
         y_next += padding + xlabel.height
     if ylabel:
         ylabel.text = self.ylabel
         ylabel.texture_update()
         ylabel.size = ylabel.texture_size
         ylabel.x = padding + x - (ylabel.width / 2. - ylabel.height / 2.)
         x_next += padding + ylabel.height
     xpoints = self._ticks_majorx
     xlabels = self._x_grid_label
     xlabel_grid = self.x_grid_label
     ylabel_grid = self.y_grid_label
     ypoints = self._ticks_majory
     ylabels = self._y_grid_label
     # now x and y tick mark labels
     if len(ylabels) and ylabel_grid:
         # horizontal size of the largest tick label, to have enough room
         ylabels[0].text = precision % ypoints[0]
         ylabels[0].texture_update()
         y1 = ylabels[0].texture_size
         y_start = y_next + (padding + y1[1] if len(xlabels) and xlabel_grid
                             else 0) +\
                             (padding + y1[1] if not y_next else 0)
         yextent = y + height - padding - y1[1] / 2.
         if self.ylog:
             ymax = log10(ymax)
             ymin = log10(ymin)
         ratio = (yextent - y_start) / float(ymax - ymin)
         y_start -= y1[1] / 2.
         func = (lambda x: 10**x) if self.ylog else lambda x: x
         y1 = y1[0]
         for k in range(len(ylabels)):
             ylabels[k].text = precision % func(ypoints[k])
             ylabels[k].texture_update()
             ylabels[k].size = ylabels[k].texture_size
             y1 = max(y1, ylabels[k].texture_size[0])
             ylabels[k].pos = tuple(
                 map(int, (x_next, y_start + (ypoints[k] - ymin) * ratio)))
         if len(ylabels) > 1 and ylabels[0].top > ylabels[1].y:
             y_overlap = True
         else:
             x_next += y1 + padding
     if len(xlabels) and xlabel_grid:
         func = log10 if self.xlog else lambda x: x
         # find the distance from the end that'll fit the last tick label
         xlabels[0].text = precision % func(xpoints[-1])
         xlabels[0].texture_update()
         xextent = x + width - xlabels[0].texture_size[0] / 2. - padding
         # find the distance from the start that'll fit the first tick label
         if not x_next:
             xlabels[0].text = precision % func(xpoints[0])
             xlabels[0].texture_update()
             x_next = padding + xlabels[0].texture_size[0] / 2.
         xmin = func(xmin)
         ratio = (xextent - x_next) / float(func(self.xmax) - xmin)
         func = (lambda x: 10**x) if self.xlog else lambda x: x
         right = -1
         for k in range(len(xlabels)):
             xlabels[k].text = precision % func(xpoints[k])
             # update the size so we can center the labels on ticks
             xlabels[k].texture_update()
             xlabels[k].size = xlabels[k].texture_size
             xlabels[k].pos = tuple(
                 map(int, (x_next + (xpoints[k] - xmin) * ratio -
                           xlabels[k].texture_size[0] / 2., y_next)))
             if xlabels[k].x < right:
                 x_overlap = True
                 break
             right = xlabels[k].right
         if not x_overlap:
             y_next += padding + xlabels[0].texture_size[1]
     # now re-center the x and y axis labels
     if xlabel:
         xlabel.x = int(x_next + (xextent - x_next) / 2. -
                        xlabel.width / 2.)
     if ylabel:
         ylabel.y = int(y_next + (yextent - y_next) / 2. -
                        ylabel.height / 2.)
         t = Matrix().translate(ylabel.center[0], ylabel.center[1], 0)
         t = t.multiply(Matrix().rotate(-radians(270), 0, 0, 1))
         ylabel.transform = t.multiply(Matrix().translate(
             -int(ylabel.center_x), -int(ylabel.center_y), 0))
     if x_overlap:
         for k in range(len(xlabels)):
             xlabels[k].text = ''
     if y_overlap:
         for k in range(len(ylabels)):
             ylabels[k].text = ''
     return x_next - x, y_next - y, xextent - x, yextent - y
示例#18
0
文件: scatter.py 项目: rcludwick/kivy
class Scatter(Widget):
    '''Scatter class. See module documentation for more information.
    '''

    auto_bring_to_front = BooleanProperty(True)
    '''If True, the widget will be automatically pushed on the top of parent
    widget list for drawing.

    :data:`auto_bring_to_front` is a :class:`~kivy.properties.BooleanProperty`,
    default to True.
    '''

    do_translation_x = BooleanProperty(True)
    '''Allow translation on X axis

    :data:`do_translation_x` is a :class:`~kivy.properties.BooleanProperty`,
    default to True.
    '''

    do_translation_y = BooleanProperty(True)
    '''Allow translation on Y axis.

    :data:`do_translation_y` is a :class:`~kivy.properties.BooleanProperty`,
    default to True.
    '''

    def _get_do_translation(self):
        return (self.do_translation_x, self.do_translation_y)

    def _set_do_translation(self, value):
        if type(value) in (list, tuple):
            self.do_translation_x, self.do_translation_y = value
        else:
            self.do_translation_x = self.do_translation_y = bool(value)
    do_translation = AliasProperty(_get_do_translation, _set_do_translation,
                                bind=('do_translation_x', 'do_translation_y'))
    '''Allow translation on X or Y axis.

    :data:`do_translation` is a :class:`~kivy.properties.AliasProperty` of
    (:data:`do_translation_x` + :data:`do_translation_y`)
    '''

    do_rotation = BooleanProperty(True)
    '''Allow rotation.

    :data:`do_rotation` is a :class:`~kivy.properties.BooleanProperty`,
    default to True.
    '''

    do_scale = BooleanProperty(True)
    '''Allow scaling.

    :data:`do_scale` is a :class:`~kivy.properties.BooleanProperty`,
    default to True.
    '''

    do_collide_after_children = BooleanProperty(False)
    '''If True, the collision detection for limiting the touch inside the
    scatter will be done after dispaching the touch to the children.
    You can put children outside the bounding box of the scatter, and be able to
    touch them.

    .. versionadded:: 1.3.0
    '''

    scale_min = NumericProperty(0.01)
    '''Minimum scaling factor allowed.

    :data:`scale_min` is a :class:`~kivy.properties.NumericProperty`, default to
    0.01
    '''

    scale_max = NumericProperty(1e20)
    '''Maximum scaling factor allowed.

    :data:`scale_max` is a :class:`~kivy.properties.NumericProperty`, default to
    1e20
    '''

    transform = ObjectProperty(Matrix())
    '''Transformation matrix.

    :data:`transform` is a :class:`~kivy.properties.ObjectProperty`, default to
    the identity matrix.
    '''

    transform_inv = ObjectProperty(Matrix())
    '''Inverse of the transformation matrix.

    :data:`transform_inv` is a :class:`~kivy.properties.ObjectProperty`, default
    to the identity matrix.
    '''

    def _get_bbox(self):
        xmin, ymin = xmax, ymax = self.to_parent(0, 0)
        for point in [(self.width, 0), (0, self.height), self.size]:
            x, y = self.to_parent(*point)
            if x < xmin:
                xmin = x
            if y < ymin:
                ymin = y
            if x > xmax:
                xmax = x
            if y > ymax:
                ymax = y
        return (xmin, ymin), (xmax - xmin, ymax - ymin)
    bbox = AliasProperty(_get_bbox, None, bind=(
        'transform', 'width', 'height'))
    '''Bounding box of the widget in parent space::

        ((x, y), (w, h))
        # x, y = lower left corner

    :data:`bbox` is a :class:`~kivy.properties.AliasProperty`.
    '''

    def _get_rotation(self):
        v1 = Vector(0, 10)
        tp = self.to_parent
        v2 = Vector(*tp(*self.pos)) - tp(self.x, self.y + 10)
        return -1.0 * (v1.angle(v2) + 180) % 360

    def _set_rotation(self, rotation):
        angle_change = self.rotation - rotation
        r = Matrix().rotate(-radians(angle_change), 0, 0, 1)
        self.apply_transform(r, post_multiply=True,
                            anchor=self.to_local(*self.center))
    rotation = AliasProperty(_get_rotation, _set_rotation, bind=(
        'x', 'y', 'transform'))
    '''Rotation value of the scatter.

    :data:`rotation` is a :class:`~kivy.properties.AliasProperty`.
    '''

    def _get_scale(self):
        p1 = Vector(*self.to_parent(0, 0))
        p2 = Vector(*self.to_parent(1, 0))
        scale = p1.distance(p2)
        return float(scale)

    def _set_scale(self, scale):
        rescale = scale * 1.0 / self.scale
        self.apply_transform(Matrix().scale(rescale, rescale, rescale),
                        post_multiply=True, anchor=self.to_local(*self.center))
    scale = AliasProperty(_get_scale, _set_scale, bind=('x', 'y', 'transform'))
    '''Scale value of the scatter.

    :data:`scale` is a :class:`~kivy.properties.AliasProperty`.
    '''

    def _get_center(self):
        return (self.bbox[0][0] + self.bbox[1][0] / 2.0,
                self.bbox[0][1] + self.bbox[1][1] / 2.0)

    def _set_center(self, center):
        if center == self.center:
            return False
        t = Vector(*center) - self.center
        trans = Matrix().translate(t.x, t.y, 0)
        self.apply_transform(trans)
    center = AliasProperty(_get_center, _set_center, bind=('bbox', ))

    def _get_pos(self):
        return self.bbox[0]

    def _set_pos(self, pos):
        _pos = self.bbox[0]
        if pos == _pos:
            return
        t = Vector(*pos) - _pos
        trans = Matrix().translate(t.x, t.y, 0)
        self.apply_transform(trans)
    pos = AliasProperty(_get_pos, _set_pos, bind=('bbox', ))

    def _get_x(self):
        return self.bbox[0][0]

    def _set_x(self, x):
        if x == self.bbox[0][0]:
            return False
        self.pos = (x, self.y)
        return True
    x = AliasProperty(_get_x, _set_x, bind=('bbox', ))

    def _get_y(self):
        return self.bbox[0][1]

    def _set_y(self, y):
        if y == self.bbox[0][1]:
            return False
        self.pos = (self.x, y)
        return True
    y = AliasProperty(_get_y, _set_y, bind=('bbox', ))

    def get_right(self):
        return self.x + self.bbox[1][0]

    def set_right(self, value):
        self.x = value - self.bbox[1][0]

    right = AliasProperty(get_right, set_right, bind=('x', 'width'))

    def get_top(self):
        return self.y + self.bbox[1][1]

    def set_top(self, value):
        self.y = value - self.bbox[1][1]

    top = AliasProperty(get_top, set_top, bind=('y', 'height'))

    def get_center_x(self):
        return self.x + self.bbox[1][0] / 2.

    def set_center_x(self, value):
        self.x = value - self.bbox[1][0] / 2.
    center_x = AliasProperty(get_center_x, set_center_x, bind=('x', 'width'))

    def get_center_y(self):
        return self.y + self.bbox[1][1] / 2.

    def set_center_y(self, value):
        self.y = value - self.bbox[1][1] / 2.
    center_y = AliasProperty(get_center_y, set_center_y, bind=('y', 'height'))

    def __init__(self, **kwargs):
        self._touches = []
        self._last_touch_pos = {}
        super(Scatter, self).__init__(**kwargs)

    def on_transform(self, instance, value):
        self.transform_inv = value.inverse()

    def collide_point(self, x, y):
        x, y = self.to_local(x, y)
        return 0 <= x <= self.width and 0 <= y <= self.height

    def to_parent(self, x, y, **k):
        p = self.transform.transform_point(x, y, 0)
        return (p[0], p[1])

    def to_local(self, x, y, **k):
        p = self.transform_inv.transform_point(x, y, 0)
        return (p[0], p[1])

    def apply_transform(self, trans, post_multiply=False, anchor=(0, 0)):
        '''
        Transforms scatter by trans (on top of its current transformation
        state).

        :Parameters:
            `trans`: transformation matrix from transformation lib.
                Transformation to be applied to the scatter widget
            `anchor`: tuple, default to (0, 0)
                The point to use as the origin of the transformation
                (uses local widget space)
            `post_multiply`: bool, default to False
                If true the transform matrix is post multiplied
                (as if applied before the current transform)
        '''
        t = Matrix().translate(anchor[0], anchor[1], 0)
        t = t.multiply(trans)
        t = t.multiply(Matrix().translate(-anchor[0], -anchor[1], 0))

        if post_multiply:
            self.transform = self.transform.multiply(t)
        else:
            self.transform = t.multiply(self.transform)

    def transform_with_touch(self, touch):
        # just do a simple one finger drag
        if len(self._touches) == 1:
            # _last_touch_pos has last pos in correct parent space,
            # just like incoming touch
            dx = (touch.x - self._last_touch_pos[touch][0]) \
                    * self.do_translation_x
            dy = (touch.y - self._last_touch_pos[touch][1]) \
                    * self.do_translation_y
            self.apply_transform(Matrix().translate(dx, dy, 0))
            return

        # we have more than one touch...
        points = [Vector(self._last_touch_pos[t]) for t in self._touches]

        # we only want to transform if the touch is part of the two touches
        # furthest apart! So first we find anchor, the point to transform
        # around as the touch farthest away from touch
        anchor = max(points, key=lambda p: p.distance(touch.pos))

        # now we find the touch farthest away from anchor, if its not the
        # same as touch. Touch is not one of the two touches used to transform
        farthest = max(points, key=anchor.distance)
        if points.index(farthest) != self._touches.index(touch):
            return

        # ok, so we have touch, and anchor, so we can actually compute the
        # transformation
        old_line = Vector(*touch.ppos) - anchor
        new_line = Vector(*touch.pos) - anchor

        angle = radians(new_line.angle(old_line)) * self.do_rotation
        self.apply_transform(Matrix().rotate(angle, 0, 0, 1), anchor=anchor)

        if self.do_scale:
            scale = new_line.length() / old_line.length()
            new_scale = scale * self.scale
            if new_scale < self.scale_min or new_scale > self.scale_max:
                scale = 1.0
            self.apply_transform(Matrix().scale(scale, scale, scale),
                                 anchor=anchor)

    def _bring_to_front(self):
        # auto bring to front
        if self.auto_bring_to_front and self.parent:
            parent = self.parent
            parent.remove_widget(self)
            parent.add_widget(self)

    def on_touch_down(self, touch):
        x, y = touch.x, touch.y

        # if the touch isnt on the widget we do nothing
        if not self.do_collide_after_children:
            if not self.collide_point(x, y):
                return False

        # let the child widgets handle the event if they want
        touch.push()
        touch.apply_transform_2d(self.to_local)
        if super(Scatter, self).on_touch_down(touch):
            touch.pop()
            self._bring_to_front()
            return True
        touch.pop()

        # if our child didn't do anything, and if we don't have any active
        # interaction control, then don't accept the touch.
        if not self.do_translation_x and \
            not self.do_translation_y and \
            not self.do_rotation and \
            not self.do_scale:
            return False

        if self.do_collide_after_children:
            if not self.collide_point(x, y):
                return False

        # grab the touch so we get all it later move events for sure
        self._bring_to_front()
        touch.grab(self)
        self._touches.append(touch)
        self._last_touch_pos[touch] = touch.pos

        return True

    def on_touch_move(self, touch):
        x, y = touch.x, touch.y
        # let the child widgets handle the event if they want
        if self.collide_point(x, y) and not touch.grab_current == self:
            touch.push()
            touch.apply_transform_2d(self.to_local)
            if super(Scatter, self).on_touch_move(touch):
                touch.pop()
                return True
            touch.pop()

        # rotate/scale/translate
        if touch in self._touches and touch.grab_current == self:
            self.transform_with_touch(touch)
            self._last_touch_pos[touch] = touch.pos

        # stop propagating if its within our bounds
        if self.collide_point(x, y):
            return True

    def on_touch_up(self, touch):
        x, y = touch.x, touch.y
        # if the touch isnt on the widget we do nothing, just try children
        if not touch.grab_current == self:
            touch.push()
            touch.apply_transform_2d(self.to_local)
            if super(Scatter, self).on_touch_up(touch):
                touch.pop()
                return True
            touch.pop()

        # remove it from our saved touches
        if touch in self._touches and touch.grab_state:
            touch.ungrab(self)
            del self._last_touch_pos[touch]
            self._touches.remove(touch)

        # stop propagating if its within our bounds
        if self.collide_point(x, y):
            return True
示例#19
0
    def transform_with_touch(self, touch):
        init_pos = self.center
        init_scale = self.scale
        init_touch_len = len(self._touches)
        #super(ZIScatter, self).transform__with__touch(touch)

        # just do a simple one finger drag
        if len(self._touches
               ) == 1 and self.scale > 1.05:  #THIS IS NOT IN ORIGINAL SCATTER:
            # _last_touch_pos has last pos in correct parent space,
            # just like incoming touch
            dx = (touch.x - self._last_touch_pos[touch][0]) \
                    * self.do_translation_x
            dy = (touch.y - self._last_touch_pos[touch][1]) \
                    * self.do_translation_y
            self.apply_transform(Matrix().translate(dx, dy, 0))
            #return

        elif len(
                self._touches
        ) == 1 and self.scale < 1.05:  #THIS IS NOT IN ORIGINAL SCATTER:
            return

        else:  #TO AVOID RETURN IN ORIGINAL SCATTER
            # we have more than one touch...
            points = [Vector(self._last_touch_pos[t]) for t in self._touches]

            # we only want to transform if the touch is part of the two touches
            # furthest apart! So first we find anchor, the point to transform
            # around as the touch farthest away from touch
            anchor = max(points, key=lambda p: p.distance(touch.pos))

            # now we find the touch farthest away from anchor, if its not the
            # same as touch. Touch is not one of the two touches used to transform
            farthest = max(points, key=anchor.distance)
            if points.index(farthest) != self._touches.index(touch):
                return

            # ok, so we have touch, and anchor, so we can actually compute the
            # transformation
            old_line = Vector(*touch.ppos) - anchor
            new_line = Vector(*touch.pos) - anchor

            angle = radians(new_line.angle(old_line)) * self.do_rotation
            self.apply_transform(Matrix().rotate(angle, 0, 0, 1),
                                 anchor=anchor)

            if self.do_scale:
                scale = new_line.length() / old_line.length()
                new_scale = scale * self.scale
                if new_scale < self.scale_min or new_scale > self.scale_max:
                    scale = 1.0
                self.apply_transform(Matrix().scale(scale, scale, scale),
                                     anchor=anchor)

        #avoid scatter leaving its box
        limitx, limity = self.is_leaving_its_box()
        if limitx or limity:
            #cancel previous apply_transform
            if init_touch_len == 1:
                ddx = ddy = 0
                if limitx: ddx = -dx
                if limity: ddy = -dy
                self.apply_transform(Matrix().translate(ddx, ddy, 0))
            else:
                if self.do_scale:
                    #self.apply_transform(Matrix().scale(scale/init_scale, scale/init_scale, scale/init_scale),
                    #             anchor=anchor)
                    # control
                    #limitx, limity = self.is_leaving_its_box()
                    #if limitx or limity:
                    self.fix_after_leaving_its_box()
示例#20
0
class GaussianBlurWindow(ScreenManager):

    image = DictProperty(
        {
            'texture': None,
            'has_alpha': False,
            'initial_radius': 0,
            'initial_matrix': Matrix(),
        },
        rebind=True)
    blurring = BooleanProperty(False)
    use_alpha = BooleanProperty(True)
    saving = BooleanProperty(False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._last_cb = None
        self._blur_thread = None

    def on_image_choose(self, imfile):
        self.imfile = imfile
        self.prepare_texture(imfile)
        self.image.texture = self.texture
        self.image.has_alpha = self.texture.colorfmt == 'bgra'
        self.current = 'blur'

    def on_radius_change(self, radius):
        self.radius = radius
        Clock.unschedule(self._last_cb)
        self._last_cb = partial(self._threaded_gaussian_blur, radius=radius)
        Clock.schedule_once(self._last_cb, .1)

    def _threaded_gaussian_blur(self, dt, radius):
        self._blur_thread = Thread(target=self.gaussian_blur, args=(radius, ))
        if self._blur_thread.is_alive():
            self._blur_thread.join()
        else:
            self._blur_thread.start()

    def prepare_texture(self, imfile):
        im = np.float32(cv.imread(imfile, -1)) / 255
        size = im.shape[1], im.shape[0]
        colorfmt = 'bgr' if im.shape[-1] == 3 else 'bgra'
        texture = Texture.create(size=size,
                                 colorfmt=colorfmt,
                                 bufferfmt='float')
        buf = cv.flip(im, 0).reshape(-1)

        self.radius = 0
        self.blur = im
        self.im = im
        self.imbuf = buf
        self.texture = texture
        texture.add_reload_observer(self.populate_texture)
        self.populate_texture()

    @mainthread
    def _set_blurring(self, blurring):
        self.blurring = blurring

    @mainthread
    def populate_texture(self):
        self.texture.blit_buffer(self.imbuf,
                                 bufferfmt=self.texture.bufferfmt,
                                 colorfmt=self.texture.colorfmt)
        self.canvas.ask_update()

    def gaussian_blur(self, radius, *args):
        '''
        This method here is used as callback for Clock.schedule_once, hence the
        ``*args`` parameter.
        '''
        self._set_blurring(True)
        if radius == 0:
            b = self.im
        else:
            b = cv.GaussianBlur(self.im, (0, 0), radius)
            if self.texture.colorfmt == 'bgra' and self.use_alpha:
                with np.errstate(divide='ignore', invalid='ignore'):
                    b = cv.merge([b[..., :3] / b[..., -1:], b[..., -1:]])
        self.blur = b
        self.imbuf = cv.flip(b, 0).reshape(-1)
        self.populate_texture()
        self._set_blurring(False)

    def save(self):
        self.saving = True
        f, e = path.splitext(self.imfile)
        alpha = ('.alpha_%s' % ('on' if self.use_alpha else 'off')
                 if self.image.has_alpha else '')
        fn = f + '.gaussian_blur.raidus_%.1f' % self.radius + alpha + e
        cv.imwrite(
            fn, self.blur * 255,
            (cv.IMWRITE_JPEG_QUALITY, 100, cv.IMWRITE_PNG_COMPRESSION, 9))
        self.saving = False
示例#21
0
    def __init__(self, **kwargs):
        super(Deflector, self).__init__(**kwargs)

        # DEFLECTOR LINE:
        # Here I rotate and translate the deflector line so that it lays exactly under the two fingers
        # and can be moved and scaled by scatter from now on. Thus I also have to pass the touches to scatter.
        # First i create the line perfectly horizontal but with the correct length. Then i add the two
        # drag points at the beginning and the end.

        self.length_origin = self.length

        with self.canvas.before:
            Color(.8, .8, .8)
            self.deflector_line = Line(points=(self.touch1.x,
                                               self.touch1.y - 1,
                                               self.touch1.x + self.length,
                                               self.touch1.y - 1))
            self.deflector_line2 = Line(points=(self.touch1.x,
                                                self.touch1.y + 1,
                                                self.touch1.x + self.length,
                                                self.touch1.y + 1))
        '''
        self.deflector_line = Image(source='graphics/beta/deflector_blue_beta2.png',
                                    allow_stretch=True,
                                    keep_ratio=False,
                                    size=(self.length, 20),
                                    center_y=(self.touch1.y),
                                    x=self.touch1.x)
        '''

        # set the right position for the two points:
        self.point1.center = self.touch1.pos
        self.point2.center = self.touch1.x + self.length, self.touch1.y
        self.point_pos_origin = [
            self.point1.x, self.point1.y, self.point2.x, self.point2.y
        ]

        # rotation:
        dx = self.touch2.x - self.touch1.x
        dy = self.touch2.y - self.touch1.y
        angle = atan2(dy, dx)

        rotation_matrix = Matrix().rotate(angle, 0, 0, 1)
        self.apply_transform(rotation_matrix,
                             post_multiply=True,
                             anchor=self.to_local(self.touch1.x,
                                                  self.touch1.y))

        # We have to adjust the bounding box of ourself to the dimension of all the canvas objects (Do we have to?)
        #self.size = (abs(self.touch2.x - self.touch1.x), abs(self.touch2.y - self.touch1.y))
        #self.pos = (min(self.touch1.x, self.touch2.x), min(self.touch1.y, self.touch2.y))

        # Now we finally add both touches we received to the _touches list of the underlying scatter class structure.
        self.touch1.grab(self)
        self._touches.append(self.touch1)
        self._last_touch_pos[self.touch1] = self.touch1.pos

        self.touch2.grab(self)
        self._touches.append(self.touch2)
        self._last_touch_pos[self.touch2] = self.touch2.pos

        self.point1.bind(size=self.size_callback)
示例#22
0
 def centerCanvas(self, *args):
     mat = Matrix().translate(Window.width / 2, Window.height / 2, 0)
     self.scatterInstance.transform = mat
示例#23
0
 def get_window_matrix(self, x=0, y=0):
     m = Matrix()
     m.translate(x, y, 0)
     return m
示例#24
0
    def parse_gcode_file(self, fn, target_layer=0, one_layer=False):
        # open file parse gcode and draw
        Logger.debug("GcodeViewerScreen: parsing file {}".format(fn))
        lastpos = [self.app.wpos[0], self.app.wpos[1],
                   -1]  # XYZ, set to initial tool position
        lastz = None
        lastdeltaz = None
        laste = 0
        lasts = 1
        layer = -1
        last_gcode = -1
        points = []
        max_x = float('nan')
        max_y = float('nan')
        min_x = float('nan')
        min_y = float('nan')
        has_e = False
        plane = XY
        rel_move = False
        self.is_visible = True
        if self.laser_mode:
            self.twod_mode = True  # laser mode implies 2D mode

        self.last_target_layer = target_layer

        # reset scale and translation
        m = Matrix()
        m.identity()
        self.ids.surface.transform = m

        # remove all instructions from canvas
        self.canv.clear()

        self.canv.add(PushMatrix())
        modal_g = 0
        cnt = 0
        found_layer = False
        x = lastpos[0]
        y = lastpos[1]
        z = lastpos[2]

        with open(fn) as f:
            # if self.last_file_pos:
            #     # jump to last read position
            #     f.seek(self.last_file_pos)
            #     self.last_file_pos= None
            #     print('Jumped to Saved position: {}'.format(self.last_file_pos))
            for ln in f:
                cnt += 1
                ln = ln.strip()
                if not ln: continue
                if ln.startswith(';'): continue
                if ln.startswith('('): continue
                p = ln.find(';')
                if p >= 0: ln = ln[:p]
                matches = self.extract_gcode.findall(ln)

                # this handles multiple G codes on one line
                gcodes = []
                d = {}
                for m in matches:
                    #print(m)
                    if m[0] == 'G' and 'G' in d:
                        # we have another G code on the same line
                        gcodes.append(d)
                        d = {}
                    d[m[0]] = float(m[1])

                gcodes.append(d)

                for d in gcodes:
                    if not d: continue

                    Logger.debug("GcodeViewerScreen: d={}".format(d))

                    # handle modal commands
                    if 'G' not in d and ('X' in d or 'Y' in d or 'Z' in d
                                         or 'S' in d):
                        d['G'] = modal_g

                    gcode = int(d['G'])

                    # G92 E0 resets E
                    if 'G' in d and gcode == 92 and 'E' in d:
                        laste = float(d['E'])
                        has_e = True

                    if 'G' in d and (gcode == 91 or gcode == 90):
                        rel_move = gcode == 91

                    # only deal with G0/1/2/3
                    if gcode > 3: continue

                    modal_g = gcode

                    # see if it is 3d printing (ie has an E axis on a G1)
                    if not has_e and ('E' in d and 'G' in d and gcode == 1):
                        has_e = True

                    if rel_move:
                        x += 0 if 'X' not in d else float(d['X'])
                        y += 0 if 'Y' not in d else float(d['Y'])
                        z += 0 if 'Z' not in d else float(d['Z'])

                    else:
                        x = lastpos[0] if 'X' not in d else float(d['X'])
                        y = lastpos[1] if 'Y' not in d else float(d['Y'])
                        z = lastpos[2] if 'Z' not in d else float(d['Z'])

                    i = 0.0 if 'I' not in d else float(d['I'])
                    j = 0.0 if 'J' not in d else float(d['J'])
                    self.rval = 0.0 if 'R' not in d else float(d['R'])

                    e = laste if 'E' not in d else float(d['E'])
                    s = lasts if 'S' not in d else float(d['S'])

                    if not self.twod_mode:
                        # handle layers (when Z changes)
                        if z == -1:
                            # no z seen yet
                            layer = -1
                            continue

                        if lastz is None:
                            # first layer
                            lastz = z
                            layer = 1

                        if z != lastz:
                            # count layers
                            layer += 1
                            lastz = z

                        # wait until we get to the requested layer
                        if layer != target_layer:
                            lastpos[2] = z
                            continue

                        if layer > target_layer and one_layer:
                            # FIXME for some reason this does not work, -- not counting layers
                            #self.last_file_pos= f.tell()
                            #print('Saved position: {}'.format(self.last_file_pos))
                            break

                        self.current_z = z

                    found_layer = True

                    Logger.debug(
                        "GcodeViewerScreen: x= {}, y= {}, z= {}, s= {}".format(
                            x, y, z, s))

                    # find bounding box
                    if math.isnan(min_x) or x < min_x: min_x = x
                    if math.isnan(min_y) or y < min_y: min_y = y
                    if math.isnan(max_x) or x > max_x: max_x = x
                    if math.isnan(max_y) or y > max_y: max_y = y

                    # accumulating vertices is more efficient but we need to flush them at some point
                    # Here we flush them if we encounter a new G code like G3 following G1
                    if last_gcode != gcode:
                        # flush vertices
                        if points:
                            self.canv.add(Color(0, 0, 0))
                            self.canv.add(
                                Line(points=points,
                                     width=1,
                                     cap='none',
                                     joint='none'))
                            points = []

                    last_gcode = gcode

                    # in slicer generated files there is no G0 so we need a way to know when to draw, so if there is an E then draw else don't
                    if gcode == 0:
                        #print("move to: {}, {}, {}".format(x, y, z))
                        # draw moves in dashed red
                        self.canv.add(Color(1, 0, 0))
                        self.canv.add(
                            Line(points=[lastpos[0], lastpos[1], x, y],
                                 width=1,
                                 dash_offset=1,
                                 cap='none',
                                 joint='none'))

                    elif gcode == 1:
                        if ('X' in d or 'Y' in d):
                            if self.laser_mode and s <= 0.01:
                                # do not draw non cutting lines
                                if points:
                                    # draw accumulated points upto this point
                                    self.canv.add(Color(0, 0, 0))
                                    self.canv.add(
                                        Line(points=points,
                                             width=1,
                                             cap='none',
                                             joint='none'))
                                    points = []

                            # for 3d printers (has_e) only draw if there is an E
                            elif not has_e or 'E' in d:
                                # if a CNC gcode file or there is an E in the G1 (3d printing)
                                #print("draw to: {}, {}, {}".format(x, y, z))
                                # collect points but don't draw them yet
                                if len(points) < 2:
                                    points.append(lastpos[0])
                                    points.append(lastpos[1])

                                points.append(x)
                                points.append(y)

                            else:
                                # a G1 with no E, treat as G0 and draw moves in red
                                #print("move to: {}, {}, {}".format(x, y, z))
                                if points:
                                    # draw accumulated points upto this point
                                    self.canv.add(Color(0, 0, 0))
                                    self.canv.add(
                                        Line(points=points,
                                             width=1,
                                             cap='none',
                                             joint='none'))
                                    points = []
                                # now draw the move in red
                                self.canv.add(Color(1, 0, 0))
                                self.canv.add(
                                    Line(points=[lastpos[0], lastpos[1], x, y],
                                         width=1,
                                         cap='none',
                                         joint='none'))

                        else:
                            # A G1 with no X or Y, maybe E only move (retract) or Z move (layer change)
                            if points:
                                # draw accumulated points upto this point
                                self.canv.add(Color(0, 0, 0))
                                self.canv.add(
                                    Line(points=points,
                                         width=1,
                                         cap='none',
                                         joint='none'))
                                points = []

                    elif gcode in [2, 3]:  # CW=2,CCW=3 circle
                        # code cribbed from bCNC
                        xyz = []
                        xyz.append((lastpos[0], lastpos[1], lastpos[2]))
                        uc, vc = self.motionCenter(gcode, plane, lastpos,
                                                   [x, y, z], i, j)

                        if plane == XY:
                            u0 = lastpos[0]
                            v0 = lastpos[1]
                            w0 = lastpos[2]
                            u1 = x
                            v1 = y
                            w1 = z
                        elif plane == XZ:
                            u0 = lastpos[0]
                            v0 = lastpos[2]
                            w0 = lastpos[1]
                            u1 = x
                            v1 = z
                            w1 = y
                            gcode = 5 - gcode  # flip 2-3 when XZ plane is used
                        else:
                            u0 = lastpos[1]
                            v0 = lastpos[2]
                            w0 = lastpos[0]
                            u1 = y
                            v1 = z
                            w1 = x
                        phi0 = math.atan2(v0 - vc, u0 - uc)
                        phi1 = math.atan2(v1 - vc, u1 - uc)
                        try:
                            sagitta = 1.0 - CNC_accuracy / self.rval
                        except ZeroDivisionError:
                            sagitta = 0.0
                        if sagitta > 0.0:
                            df = 2.0 * math.acos(sagitta)
                            df = min(df, math.pi / 4.0)
                        else:
                            df = math.pi / 4.0

                        if gcode == 2:
                            if phi1 >= phi0 - 1e-10: phi1 -= 2.0 * math.pi
                            ws = (w1 - w0) / (phi1 - phi0)
                            phi = phi0 - df
                            while phi > phi1:
                                u = uc + self.rval * math.cos(phi)
                                v = vc + self.rval * math.sin(phi)
                                w = w0 + (phi - phi0) * ws
                                phi -= df
                                if plane == XY:
                                    xyz.append((u, v, w))
                                elif plane == XZ:
                                    xyz.append((u, w, v))
                                else:
                                    xyz.append((w, u, v))
                        else:
                            if phi1 <= phi0 + 1e-10: phi1 += 2.0 * math.pi
                            ws = (w1 - w0) / (phi1 - phi0)
                            phi = phi0 + df
                            while phi < phi1:
                                u = uc + self.rval * math.cos(phi)
                                v = vc + self.rval * math.sin(phi)
                                w = w0 + (phi - phi0) * ws
                                phi += df
                                if plane == XY:
                                    xyz.append((u, v, w))
                                elif plane == XZ:
                                    xyz.append((u, w, v))
                                else:
                                    xyz.append((w, u, v))

                        xyz.append((x, y, z))
                        # plot the points
                        points = []
                        for t in xyz:
                            x1, y1, z1 = t
                            points.append(x1)
                            points.append(y1)
                            max_x = max(x1, max_x)
                            min_x = min(x1, min_x)
                            max_y = max(y1, max_y)
                            min_y = min(y1, min_y)

                        self.canv.add(Color(0, 0, 0))
                        self.canv.add(
                            Line(points=points,
                                 width=1,
                                 cap='none',
                                 joint='none'))
                        points = []

                    # always remember last position
                    lastpos = [x, y, z]
                    laste = e
                    lasts = s

        if not found_layer:
            # we hit the end of file before finding the layer we want
            Logger.info(
                "GcodeViewerScreen: last layer was at {}".format(lastz))
            self.last_target_layer -= 1
            return

        # flush any points not yet drawn
        if points:
            # draw accumulated points upto this point
            self.canv.add(Color(0, 0, 0))
            self.canv.add(
                Line(points=points, width=1, cap='none', joint='none'))
            points = []

        # center the drawing and scale it
        dx = max_x - min_x
        dy = max_y - min_y
        if dx == 0 or dy == 0:
            Logger.warning(
                "GcodeViewerScreen: size is bad, maybe need 2D mode")
            return

        self.bounds = [dx, dy]

        dx += 4
        dy += 4
        Logger.debug("GcodeViewerScreen: dx= {}, dy= {}".format(dx, dy))

        # add in the translation to center object
        self.tx = -min_x - dx / 2
        self.ty = -min_y - dy / 2
        self.canv.insert(1, Translate(self.tx, self.ty))
        Logger.debug("GcodeViewerScreen: tx= {}, ty= {}".format(
            self.tx, self.ty))

        # scale the drawing to fit the screen
        if abs(dx) > abs(dy):
            scale = self.ids.surface.width / abs(dx)
            if abs(dy) * scale > self.ids.surface.height:
                scale *= self.ids.surface.height / (abs(dy) * scale)
        else:
            scale = self.ids.surface.height / abs(dy)
            if abs(dx) * scale > self.ids.surface.width:
                scale *= self.ids.surface.width / (abs(dx) * scale)

        Logger.debug("GcodeViewerScreen: scale= {}".format(scale))
        self.scale = scale
        self.canv.insert(1, Scale(scale))
        # translate to center of canvas
        self.offs = self.ids.surface.center
        self.canv.insert(
            1, Translate(self.ids.surface.center[0],
                         self.ids.surface.center[1]))
        Logger.debug("GcodeViewerScreen: cx= {}, cy= {}".format(
            self.ids.surface.center[0], self.ids.surface.center[1]))
        Logger.debug("GcodeViewerScreen: sx= {}, sy= {}".format(
            self.ids.surface.size[0], self.ids.surface.size[1]))

        # axis Markers
        self.canv.add(Color(0, 1, 0, mode='rgb'))
        self.canv.add(
            Line(points=[0, -10, 0, self.ids.surface.height / scale],
                 width=1,
                 cap='none',
                 joint='none'))
        self.canv.add(
            Line(points=[-10, 0, self.ids.surface.width / scale, 0],
                 width=1,
                 cap='none',
                 joint='none'))

        # tool position marker
        if self.app.is_connected:
            x = self.app.wpos[0]
            y = self.app.wpos[1]
            r = (10.0 / self.ids.surface.scale) / scale
            self.canv.add(Color(1, 0, 0, mode='rgb', group="tool"))
            self.canv.add(Line(circle=(x, y, r), group="tool"))

        # self.canv.add(Rectangle(pos=(x, y-r/2), size=(1/scale, r), group="tool"))
        # self.canv.add(Rectangle(pos=(x-r/2, y), size=(r, 1/scale), group="tool"))

        self.canv.add(PopMatrix())
        self._loaded_ok = True
        Logger.debug("GcodeViewerScreen: done loading")
示例#25
0
 def _set_rotation(self, rotation):
     angle_change = self.rotation - rotation
     r = Matrix().rotate(-radians(angle_change), 0, 0, 1)
     self.apply_transform(r,
                          post_multiply=True,
                          anchor=self.to_local(*self.center))
示例#26
0
文件: main.py 项目: deganii/2.131-UI
 def _do_reset_scatter(self, val):
     # move the
     mat = Matrix().scale(10, 10, 10).translate(0, -150, 0)
     self._scatter.transform = mat
示例#27
0
 def _set_center(self, center):
     if center == self.center:
         return False
     t = Vector(*center) - self.center
     trans = Matrix().translate(t.x, t.y, 0)
     self.apply_transform(trans)
示例#28
0
文件: main.py 项目: deganii/2.131-UI
    def build(self):
        self.init_GPIO()

        #layout = BoxLayout(orientation='vertical')
        layout = FloatLayout(size=(800, 480), pos=(0, 0))

        self._toggle = ToggleButton(text='LED OFF',
                                    size_hint=(0.2, 0.2),
                                    pos_hint={'pos': (0.8, 0)})

        self._snap = Button(text='Capture',
                            size_hint=(0.2, 0.2),
                            pos_hint={'pos': (0.8, 0.2)})

        self._snapref = Button(text='Reference',
                               size_hint=(0.2, 0.2),
                               pos_hint={'pos': (0.8, 0.4)})

        # self._demo = Button(text='Demo Results',
        #    size_hint=(0.2,0.1), pos_hint={'pos': (0.0, 0.7)})

        self._auto_centroid = ImageButton(
            size_hint=(0.1, 0.1),
            pos_hint={'pos': (0.7, 0)},
            source='/home/pi/2.131-UI/img/distribution_centroid_off.png')

        self._object_detection = ImageButton(
            size_hint=(0.1, 0.1),
            pos_hint={'pos': (0.7, 0.1)},
            source='/home/pi/2.131-UI/img/object_detection_off.png')

        self._reset_scatter = ImageButton(
            size_hint=(0.1, 0.1),
            pos_hint={'pos': (0.7, 0.2)},
            source='/home/pi/2.131-UI/img/reset_scatter.png')

        self._exit = Button(text='X',
                            size_hint=(0.05, 0.05),
                            pos_hint={'pos': (0.95, 0.95)})

        self._fps = Label(text='FPS: 0',
                          size_hint=(0.1, 0.1),
                          pos_hint={'pos': (0.8, 0.9)})
        self._temp = Label(text='Temp: 0',
                           size_hint=(0.1, 0.1),
                           pos_hint={'pos': (0.6, 0.9)})

        dev_ip = self.get_ip_address()
        self._ip = Label(text='IP: %s' % dev_ip,
                         size_hint=(0.1, 0.1),
                         pos_hint={'pos': (0.3, 0.9)})

        self._uploading = Label(text='Uploading...',
                                size_hint=(0.2, 0.1),
                                pos_hint={'pos': (-1, -1)},
                                color=[0, 0, 1, 0])
        self._uploadingAmt = Label(text='',
                                   size_hint=(0.2, 0.1),
                                   pos_hint={'pos': (-1, -1)},
                                   color=[0, 0, 1, 0])

        self._exposure = Label(text='Exposure: 0',
                               size_hint=(0.2, 0.1),
                               pos_hint={'pos': (0, 0)})

        self._centroid = Label(text='C:0',
                               size_hint=(0.1, 0.1),
                               pos_hint={'pos': (0.79, 0.83)},
                               color=[1, 0, 0, 1])

        self._exposure_slider = Slider(min=0,
                                       max=2500,
                                       value=1358,
                                       size_hint=(0.5, 0.1),
                                       pos_hint={'pos': (0.2, 0)})

        self._upload_progress = ProgressBar(max=100,
                                            size_hint=(0.5, 0.1),
                                            pos_hint={'pos': (-1, -1)})

        # self._camera = Camera2131(resolution=(1280,960),
        #                           fourcc="GREY",
        #                           capture_resolution=(3872, 2764),
        #                           capture_fourcc="Y16 ",
        #                           size_hint=(1,1),
        #                           pos_hint={'pos':(0,0)},
        #                           play=True, )

        self._camera = Camera2131(
            resolution=(640, 480),
            fourcc="GREY",
            capture_resolution=(640, 480),
            capture_fourcc="GREY",
            size_hint=(1, 1),
            pos_hint={'pos': (0, 0)},
            play=True,
        )

        # self._camera = Camera2131(resolution=(1280,720),
        #                         play=True, fourcc="GREY")

        # self._camera = Camera2131(resolution=(3872, 2764),
        #                       play=True, fourcc="Y16 ")

        # self._camera = Camera2131(resolution=(1920,1080),
        #                        play=True, fourcc="GREY")

        # self._camera = Camera2131(resolution=(2560, 1920),
        #                        play=True, fourcc="GREY")

        self._dropdown = DropDown()

        # create a big main button
        # self._imageResultsButton = Button(text='Image Explorer',pos_hint={'pos': (0.0, 0.6)}, size_hint=(0.2, 0.1))

        # show the dropdown menu when the main button is released
        # note: all the bind() calls pass the instance of the caller (here, the
        # mainbutton instance) as the first argument of the callback (here,
        # dropdown.open.).
        # self._imageResultsButton.bind(on_release=self._dropdown.open)

        # one last thing, listen for the selection in the dropdown list and
        # assign the data to the button text.
        # self._dropdown.bind(on_select=lambda instance, x: setattr(self._imageResultsButton, 'text', x))

        self._histogram = Histogram(size_hint=(0.2, 0.3),
                                    pos_hint={'pos': (0.8, 0.6)})

        # self._demo.bind(on_press=self._show_demo_results)
        self._toggle.bind(on_press=self._led_toggle)
        self._snap.bind(on_press=self._request_capture)
        self._snapref.bind(on_press=self._request_ref_capture)
        self._exit.bind(on_press=self._exit_app)
        self._auto_centroid.bind(on_press=self._auto_change_exposure)
        self._object_detection.bind(on_press=self._toggle_object_detection)
        self._exposure_slider.bind(value=self._change_exposure)
        self._reset_scatter.bind(on_press=self._do_reset_scatter)

        #update.bind(on_press=self._update_histogram)
        self._camera.fbind('on_frame_complete', self._update_histogram)

        self._scatter = Scatter(
            size_hint=(None, None),
            size=(200, 200),
        )
        self._scatter.add_widget(self._camera)
        #layout.add_widget(self._camera)
        layoutInner = FloatLayout(size_hint=(0.8, 1),
                                  pos_hint={
                                      'x': 0,
                                      'y': 0
                                  })
        layoutInner.add_widget(self._scatter)
        layout.add_widget(layoutInner)

        mat = Matrix().scale(10, 10, 10).translate(0, -150, 0)
        self._scatter.apply_transform(mat)
        # layout.add_widget(self._imageResultsButton)
        layout.add_widget(self._uploading)
        layout.add_widget(self._uploadingAmt)
        # layout.add_widget(self._demo)
        layout.add_widget(self._histogram)
        layout.add_widget(self._snap)
        layout.add_widget(self._snapref)
        layout.add_widget(self._exit)
        layout.add_widget(self._centroid)
        layout.add_widget(self._exposure_slider)
        layout.add_widget(self._upload_progress)
        layout.add_widget(self._auto_centroid)
        layout.add_widget(self._object_detection)
        layout.add_widget(self._reset_scatter)

        layout.add_widget(self._exposure)
        layout.add_widget(self._fps)
        layout.add_widget(self._temp)
        layout.add_widget(self._ip)
        Clock.schedule_interval(self._update_fps, 2)
        layout.add_widget(self._toggle)
        #layout.add_widget(update)

        self._is_updating = False
        # self.updateImages()
        return layout
示例#29
0
    def transform_with_touch(self, touch):
        changed = False
        x = self.bbox[0][0]
        y = self.bbox[0][1]
        width = self.bbox[1][0]
        height = self.bbox[1][1]
        mid_x = x + width / 2
        mid_y = y + height / 2
        inner_width = width * 0.5
        inner_height = height * 0.5
        left = mid_x - (inner_width / 2)
        right = mid_x + (inner_width / 2)
        top = mid_y + (inner_height / 2)
        bottom = mid_y - (inner_height / 2)

        # just do a simple one finger drag
        if len(self._touches) == self.translation_touches:
            # _last_touch_pos has last pos in correct parent space,
            # just like incoming touch
            dx = (touch.x - self._last_touch_pos[touch][0]) \
                * self.do_translation_x
            dy = (touch.y - self._last_touch_pos[touch][1]) \
                * self.do_translation_y
            dx = dx / self.translation_touches
            dy = dy / self.translation_touches
            if (
                    touch.x > left and touch.x < right and touch.y < top
                    and touch.y > bottom or self.move_lock
            ) and not self.scale_lock_left and not self.scale_lock_right and not self.scale_lock_top and not self.scale_lock_bottom:
                self.move_lock = True
                self.apply_transform(Matrix().translate(dx, dy, 0))
                changed = True

        change_x = touch.x - self.prev_x
        change_y = touch.y - self.prev_y
        anchor_sign = 1
        sign = 1
        if abs(
                change_x
        ) >= 9 and not self.move_lock and not self.scale_lock_top and not self.scale_lock_bottom:
            if change_x < 0:
                sign = -1
            if (touch.x < left
                    or self.scale_lock_left) and not self.scale_lock_right:
                self.scale_lock_left = True
                self.pos = (self.pos[0] + (sign * 10), self.pos[1])
                anchor_sign = -1
            elif (touch.x > right
                  or self.scale_lock_right) and not self.scale_lock_left:
                self.scale_lock_right = True
            self.size[0] = self.size[0] + (sign * anchor_sign * 10)
            self.prev_x = touch.x
            changed = True
        if abs(
                change_y
        ) >= 9 and not self.move_lock and not self.scale_lock_left and not self.scale_lock_right:
            if change_y < 0:
                sign = -1
            if (touch.y > top
                    or self.scale_lock_top) and not self.scale_lock_bottom:
                self.scale_lock_top = True
            elif (touch.y < bottom
                  or self.scale_lock_bottom) and not self.scale_lock_top:
                self.scale_lock_bottom = True
                self.pos = (self.pos[0], self.pos[1] + (sign * 10))
                anchor_sign = -1
            self.size[1] = self.size[1] + (sign * anchor_sign * 10)
            self.prev_y = touch.y
            changed = True
        return changed
示例#30
0
    def build(self):
        self.init_GPIO()

        layout = FloatLayout(size=(800, 480), pos=(0, 0))

        self._toggle = ToggleButton(text='LED OFF',
                                    size_hint=(0.2, 0.2),
                                    pos_hint={'pos': (0.8, 0)})

        self._snap = Button(text='COUNT',
                            size_hint=(0.2, 0.2),
                            pos_hint={'pos': (0.8, 0.2)})

        self._object_detection = ImageButton(
            size_hint=(0.1, 0.1),
            pos_hint={'pos': (0.7, 0.0)},
            source=self.img_path('object_detection_off.png'))

        self._reset_scatter = ImageButton(
            size_hint=(0.1, 0.1),
            pos_hint={'pos': (0.7, 0.1)},
            source=self.img_path('reset_scatter.png'))

        self._logo = Image(size_hint=(0.3, 0.2),
                           pos_hint={'pos': (-0.03, 0.84)},
                           source=self.img_path('ids.png'))

        self._exit = ImageButton(size_hint=(0.05, 0.05),
                                 pos_hint={'pos': (0.96, 0.95)},
                                 source=self.img_path('close-white.png'))

        red, white, kivy_blue = (1, 0, 0, 1), (1, 1, 1,
                                               1), (51. / 255, 164. / 255,
                                                    206. / 255, 1)

        self._fps = Label(text='FPS: 0',
                          size_hint=(0.1, 0.1),
                          pos_hint={'pos': (0.8, 0.9)},
                          color=red)
        self._temp = Label(text='Temp: 0',
                           size_hint=(0.1, 0.1),
                           pos_hint={'pos': (0.6, 0.9)},
                           color=white)

        dev_ip = self.get_ip_address()

        self._ip = Label(text='IP: %s' % dev_ip,
                         size_hint=(0.1, 0.1),
                         pos_hint={'pos': (0.4, 0.9)},
                         color=white)
        self._exposure = Label(text='Exposure: 0',
                               size_hint=(0.2, 0.1),
                               pos_hint={'pos': (0, 0)})

        self._centroid = Label(text='C:0',
                               size_hint=(0.1, 0.1),
                               pos_hint={'pos': (0.79, 0.83)},
                               color=white)

        self._exposure_slider = Slider(min=0,
                                       max=2500,
                                       value=1358,
                                       size_hint=(0.5, 0.1),
                                       pos_hint={'pos': (0.2, 0)})

        # self._camera = Camera2131(resolution=(1280,960),
        #                           fourcc="GREY",
        #                           capture_resolution=(3872, 2764),
        #                           capture_fourcc="Y16 ",
        #                           size_hint=(1,1),
        #                           pos_hint={'pos':(0,0)},
        #                           play=True, )

        # self._camera = CameraIDS(resolution=(640, 480),
        #                           fourcc="GREY",
        #                           capture_resolution=(640, 480),
        #                           capture_fourcc="GREY",
        #                           size_hint=(1,1),
        #                           pos_hint={'pos':(0,0)},
        #                           play=True)

        self._histogram = Histogram(size_hint=(0.2, 0.25),
                                    pos_hint={'pos': (0.8, 0.65)})

        self._tracker_histogram = TrackerHistogram(
            size_hint=(0.2, 0.25), pos_hint={'pos': (0.8, 0.4)})

        # self._roi_tracker = ROITracker(self._camera.resolution,
        #     size_hint=(0.2,0.25), pos_hint={'pos':(0.02,0.6)})
        # self._roi_tracker.bind(roi_Offset=self._update_roi)

        # self._demo.bind(on_press=self._show_demo_results)
        self._toggle.bind(on_press=self._led_toggle)
        self._snap.bind(on_press=self._start_count)
        self._exit.bind(on_press=self._exit_app)
        self._object_detection.bind(on_press=self._toggle_object_detection)
        self._exposure_slider.bind(value=self._change_exposure)
        self._reset_scatter.bind(on_press=self._do_reset_scatter)

        # self._camera.fbind('on_frame_complete',self._update_histogram)

        self._scatter = Scatter(
            size_hint=(None, None),
            size=(200, 200),
        )
        # self._scatter.add_widget(self._camera)
        # layoutInner = FloatLayout(size_hint=(0.8, 1), pos_hint={'x':0,'y':0})
        # layoutInner.add_widget(self._scatter)
        layout.add_widget(self._scatter)

        mat = Matrix().scale(10, 10, 10).translate(0, -150, 0)
        self._scatter.apply_transform(mat)
        layout.add_widget(self._histogram)
        layout.add_widget(self._tracker_histogram)
        layout.add_widget(self._snap)
        layout.add_widget(self._exit)
        layout.add_widget(self._exposure_slider)
        layout.add_widget(self._object_detection)
        layout.add_widget(self._reset_scatter)

        layout.add_widget(self._exposure)
        layout.add_widget(self._fps)
        layout.add_widget(self._temp)
        layout.add_widget(self._ip)
        Clock.schedule_interval(self._update_fps, 2)
        layout.add_widget(self._toggle)
        layout.add_widget(self._logo)
        # layout.add_widget(self._roi_tracker)
        self._is_updating = False
        return layout