KIVY collide_point vertex Rectangle

Question:

I am having a custom widget with a rectangle and horizontal line both created using Vertex Instruction. I want to check whether users is touching within rectangle or horizontal line in my widget. Tried using Group but unable to find whether user touched rectangle or Line. Can you please provide me with clue.
Find below sample code.

from kivy.app import App
from kivy.graphics import Line
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.lang import Builder

KV = '''
<Actor>:
    id: Actor
    canvas:
        Color:
            rgba: 0,1,0,1
        Rectangle:
            group: 'rect'
            size: 100, 30
            pos: 0, root.height - 30
        Line:
            group: 'line'
            points: 50, root.height - 30, 50, 0
            width:2
    Label:
        id: _actr_lbl
        text: 'Hello World'
        markup: True
        color: 0,0,0,1
        size_hint: None, None
        size: 100, 30
        pos: 0, root.height - 30
'''

class Actor(Scatter):
    def __init__(self, **kwargs):
        super(Actor, self).__init__(**kwargs)

    def on_touch_down(self, touch):

        print('Touch location {} Actor location {} Actor Size {}'.format(touch, self.pos, self.size))
        if self.collide_point(*touch.pos) :
           for aVertex in self.canvas.get_group('rect') :
               try:
                   print ('Vertex size {} and pos'.format(aVertex.size, aVertex.pos))
               except:
                   pass
           return True

        return super(Actor, self).on_touch_down(touch)

class MyPaintApp(App):

    def build(self):
        Builder.load_string(KV)
        root = RelativeLayout()
        root.add_widget(Actor(pos_hint={'center_x':0.5, 'center_y':0.5}, size_hint=(.2, 1.)))
        return root

if __name__ == '__main__':
    MyPaintApp().run()

Thanks in advance

Asked By: KJG

||

Answers:

You can do a simple bounding box check, but you must take into account the fact that the touch is in the parent coordinate system. So you can convert the touch position to local coordinates, then do the test. Here is an example for the Rectangle:

def on_touch_down(self, touch):

    print('Touch location {} Actor location {} Actor Size {}'.format(touch, self.pos, self.size))
    if self.collide_point(*touch.pos) :
        localTouchPos = self.to_local(*touch.pos)
        for aVertex in self.canvas.get_group('rect') :
            print('tVertex size {} and pos {}'.format(aVertex.size, aVertex.pos))
            intersection = True
            if localTouchPos[0] < aVertex.pos[0]:
                intersection = False
            elif localTouchPos[0] > aVertex.pos[0] + aVertex.size[0]:
                intersection = False
            if localTouchPos[1] < aVertex.pos[1]:
                intersection = False
            elif localTouchPos[1] > aVertex.pos[1] + aVertex.size[1]:
                intersection = False
        print('intersection =', intersection)
        return True

    return super(Actor, self).on_touch_down(touch)

You can do something similar for the Line, but it may be a bit more complicated if you want to do a general Line. If your Line is always vertical, it hould be very similar.

Answered By: John Anderson
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.