omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Draw line between 2 points using scene shapenode and ui.Path()

    Pythonista
    shapenode path scene
    2
    6
    4312
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • inaccessiblerail
      inaccessiblerail last edited by inaccessiblerail

      Hello, this is my first post here - I’m new to Python and Pythonista. As I learn I’ve hit a strange issue with drawing paths I cannot work out.

      I’ve been trying to draw a line between 2 points - a fixed point at the centre of the screen and a touched point on the screen - and whilst I can get nodes drawing on screen OK, the line itself is not in the right position. I’ve posted my code below to help replicate the issue.

      It’s not in my code below, but I’ve also tried numerous workarounds such as rotating the node, changing anchor points dynamically and calculating the vector between the points, all of which would work in Swift SpriteKit (which I have years of experience with) but don’t seem to work here - the nodes just end up in seemingly random positions with no pattern I can discern.

      Any pointers in the right direction would be very much appreciated - many thanks.

      import ui
      from scene import *	
      		
      class MyScene (Scene):
      
      	def setup(self):
      
      		self.background_color = '#00006b'
      		self.centre = Point(self.size.w/2, self.size.h/2)
      									
      	def update(self):
      		pass
      		
      	def touch_began(self, touch):
      		
      		# Place dots in scene to test touch and centre points are correct
      		
      		dotA = Dot(location = self.centre)
      		self.add_child(dotA)
      		
      		dotB = Dot(location = touch.location)
      		self.add_child(dotB)
      		
      		# The issue: line is right length but never right position or angle
      		# Draw line between the touched point and centre of the screen
      		
      		path = ui.Path()
      		path.line_width = 4.0
      		path.move_to(self.centre.x, self.centre.y)
      		path.line_to(touch.location.x, touch.location.y)
      	
      		line = ShapeNode()
      		line.path = path
      		line.position = (self.centre.x, self.centre.y)
      		line.anchor_point = (0, 0)
      		line.stroke_color = 'white'
      		self.add_child(line)
      	
      class Dot(ShapeNode):
      
      	def __init__(self, *, location, **kwargs):
      
      		circle = ui.Path.oval(0,0,20,20)
      		super().__init__(circle, fill_color='white', **kwargs)
      		self.position = (location.x, location.y)
      		
      run(MyScene())
      
      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp @inaccessiblerail last edited by cvp

        @inaccessiblerail in ui, y=0 at top but in scene, y=0 at bottom
        the little modification here works for touchs at up-right of center, use it as first step to solve all 😀

                path.line_to(touch.location.x, ui.get_screen_size()[1]  - touch.location.y) 
        

        1 Reply Last reply Reply Quote 0
        • inaccessiblerail
          inaccessiblerail last edited by inaccessiblerail

          @cvp Thanks, that’s a very helpful tip on the ui vs scene coordinates. I’ve worked out your screenshot for up right touches - I’ll work on the other parts of the screen now. Thanks for your help!

          cvp 1 Reply Last reply Reply Quote 0
          • cvp
            cvp @inaccessiblerail last edited by cvp

            @inaccessiblerail I'm really sorry that I'm not able to help you better but I never use Scene.
            I've remarked that if you touch at right,bottom of the center, the line starts from the correct x but with y = 0. I suppose that anchor_point or position is the reason but I can't help.
            There are some guys in this forum who could help you but this is an holiday period 😢

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp last edited by

              This works

                      path.move_to(-dx,dy)
                      path.line_to(-dx,dy)
                      path.move_to(0,0)
                      path.line_to(dx,-dy)
              
                      line = ShapeNode()
                      line.path = path
                      line.position = (self.centre.x, self.centre.y)
                      #line.anchor_point = (0, 0) # default = 0.5,0.5
                      line.stroke_color = 'white'
                      self.add_child(line) 
              

              1 Reply Last reply Reply Quote 0
              • inaccessiblerail
                inaccessiblerail last edited by inaccessiblerail

                @cvp - that’s a tremendous help, many thanks.

                For anyone who might want help with ui and scene path drawing when searching in the future, here’s the complete working code (when using the ‘new’ render loop not the classic render loop):

                import ui
                from scene import *	
                		
                class MyScene (Scene):
                
                	def setup(self):
                
                		self.background_color = '#00006b'
                		self.centre = Point(self.size.w/2, self.size.h/2)
                							
                	def update(self):
                		pass
                		
                	def touch_began(self, touch):
                		
                		# Calculate vector between centre point and touched point
                		dx = touch.location.x - self.centre.x
                		dy = touch.location.y - self.centre.y
                		
                		# Draw path from centre point to touched point
                		path = ui.Path()
                		path.line_width = 4.0
                		path.move_to(-dx,dy)
                		path.line_to(-dx,dy)
                		path.move_to(0,0)
                		path.line_to(dx,-dy)
                
                		# Create line node from path
                		line = ShapeNode()
                		line.path = path
                		line.position = (self.centre.x, self.centre.y)
                		line.stroke_color = 'white'
                		self.add_child(line) 
                		 
                		# Place dots at centre and touch points
                		dotA = Dot(location = self.centre)
                		self.add_child(dotA)
                		
                		dotB = Dot(location = touch.location)
                		self.add_child(dotB)
                		
                class Dot(ShapeNode):
                	
                	def __init__(self, *, location, **kwargs):
                
                		circle = ui.Path.oval(0,0,20,20)
                		super().__init__(circle, fill_color='white', **kwargs)
                		self.position = (location.x, location.y)
                		
                run(MyScene())
                
                
                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors