Search code examples
kivykivy-language

Kivy position line based on other widget position


I'm trying to draw the orbit groundtrack of the ISS on a map and I think I know how I'll do that once I figure out how to position the line on the map.

To figure out line positioning I'm trying to draw a line from the bottom left of the map to the top right, using the following code (minus extra widgets):

#:import kivy kivy
#:import win kivy.core.window
<Orbit_Screen>:
    name: 'orbit'
    FloatLayout:
        id: orbit_layout
        Image:
            id: OrbitMap
            source: 'C:/Users/Sam/PycharmProjects/Mimic-Development/Pi/imgs/orbit/map.jpg'
            pos_hint: {"center_x": 0.5, "center_y": 0.56}
            size: (500,300)
            #size_hint_y: 0.598
            size_hint: (None,None)
            allow_stretch: False
            keep_ratio: True
        Widget:
            id: TDRS10
            col: (1,1,1,1)
            pos_hint: {'center_x': 0.5, 'center_y': 0.5}
            size_hint: '0.01dp', '0.02dp'
            canvas:
                Color:
                    rgba: self.col
                Ellipse:
                    pos: self.pos
                    size: self.size
                Line:
                    points: (OrbitMap.x,OrbitMap.y,OrbitMap.width,OrbitMap.height)
                    joint: "round"

Which produces the following image: enter image description here

Can anyone help me understand why the starting x coordinate matches with the map but the y coordinate is below the image and the top right coordinates both fall short? Thanks for any assistance. I really thought I understood widget positioning but I guess not.


Solution

  • The OrbitMap is scaled and translated to meet your pos_hint and size specifications from your kv. Assuming that your orbit line coordinates are in pixels relative to the original map, then you will need to translate and scale those coordinates to match the scale and translation applied to the map image. I believe you can accomplish that using this in your kv for the Widget canvas:

    Widget:
        id: TDRS10
        col: (1,1,1,1)
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
        size_hint: '0.01dp', '0.02dp'
        canvas:
            PushMatrix:
            Translate:
                xy: (OrbitMap.x + (OrbitMap.width - OrbitMap.norm_image_size[0])/2, OrbitMap.y + (OrbitMap.height - OrbitMap.norm_image_size[1])/2)
            Scale:
                origin: 0,0
                x: OrbitMap.norm_image_size[0] / OrbitMap.texture_size[0] if OrbitMap.texture_size[0] > 0 else 1
                y: OrbitMap.norm_image_size[1] / OrbitMap.texture_size[1] if OrbitMap.texture_size[1] > 0 else 1
            Color:
                rgba: self.col
            Ellipse:
                pos: self.pos
                size: self.size
            Line:    # test diagonal line 1
                points: (0, 0, OrbitMap.texture_size[0], OrbitMap.texture_size[1])
                joint: "round"
            Line:    # test diagonal line 2
                points: (0, OrbitMap.texture_size[1], OrbitMap.texture_size[0], 0)
                joint: "round"
            Line:    # test norizontal line
                points: (0, OrbitMap.texture_size[1]/2, OrbitMap.texture_size[0], OrbitMap.texture_size[1]/2)
                joint: "round"
            Line:    # test vertical line
                points: (OrbitMap.texture_size[0]/2, 0, OrbitMap.texture_size[0]/2, OrbitMap.texture_size[1])
                joint: "round"
            PopMatrix:
    

    The above uses the canvas Scale and Translate matrices to convert the line coordinates. I have replaced your orbit line with some test lines to make sure that the scheme works.