Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How can I draw a shape area around a polyline? So I can move polyline with mouse.

How can I draw a shape area around a polyline? So I can move polyline with mouse.

Scheduled Pinned Locked Moved Unsolved General and Desktop
qt4boundingrectshapepolygonpolyline
11 Posts 3 Posters 5.0k Views
  • 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.
  • H helloworld12345

    The shape function is used to replace boundingRect. Polyline is not an enclosed area, so there is no concept inside or outside as polygon.

    The shape should be an area around the polyline, so the shape should be able to detect the mouse cursor when it's around the polyline(for example when distance is 10).

    Does anyone have experience on this? I really appreciate any suggestions.

    raven-worxR Offline
    raven-worxR Offline
    raven-worx
    Moderators
    wrote on last edited by
    #2

    @helloworld12345
    by polyline you mean a list of points right?
    I think the easiest would be to draw rectangles for each line segment and merge them each into a QPainterPath. When you are done call QPainterPath::toFillPolygon().
    Now the problem is just to calculate the coordinates of the rectangles based on the line-segments and your desired spacing.

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    H 2 Replies Last reply
    0
    • H Offline
      H Offline
      helloworld12345
      wrote on last edited by helloworld12345
      #3

      @raven-worx said in How can I draw a shape area around a polyline? So I can move polyline with mouse.:

      toFillPolygon()

      Thanks raven.

      1. I didn't use toFillPolygon, but use addPolygon, it works partially, most but not all area can be dragged by mouse.
      2. I added eclipses around the points of polyline since rect can't cover the turning area of polyline, but it seems the eclipses didn't response when I use mouse to drag it, you have any idea? Below is the simplified code.
      def shape(self):  
          final_shape = QPainterPath()
          
          ##
          ##here calcuclate the each polygon for each line session, store the points in polygons
          ##
          
          for k in range(0, len(polygons)):
              polygon = QPolygonF([polygons[k][0], polygons[k][1],  polygons[k][2], polygons[k][3]])
              final_shape.addPolygon(polygon)
      
      
          for p in self._polyline:
              newpath = QPainterPath()
              newpath.addEllipse(p, 15, 15)
              final_shape = final_shape.united(newpath)
              
          return final_shape
      
      1 Reply Last reply
      0
      • raven-worxR raven-worx

        @helloworld12345
        by polyline you mean a list of points right?
        I think the easiest would be to draw rectangles for each line segment and merge them each into a QPainterPath. When you are done call QPainterPath::toFillPolygon().
        Now the problem is just to calculate the coordinates of the rectangles based on the line-segments and your desired spacing.

        H Offline
        H Offline
        helloworld12345
        wrote on last edited by
        #4

        @raven-worx if you happen to know some example code in which several graphics(rect + ellipse) are combined in shape, that would definitely help a lot.

        1 Reply Last reply
        0
        • raven-worxR raven-worx

          @helloworld12345
          by polyline you mean a list of points right?
          I think the easiest would be to draw rectangles for each line segment and merge them each into a QPainterPath. When you are done call QPainterPath::toFillPolygon().
          Now the problem is just to calculate the coordinates of the rectangles based on the line-segments and your desired spacing.

          H Offline
          H Offline
          helloworld12345
          wrote on last edited by
          #5

          @raven-worx
          you can see I drew a rect for each line session, an ellipse for each point(rect doesn't cover the point). With all these rects and ellipses, the polyline is covered totally.

          But at the left-most, right-most, up-most, bottom-most area of the shape, my mouse can't drag the polyline. And at the intersection area of rect and ellipse, I can't drag either, does any one have idea?

          In paint function, I draw my shape area, please see below picture. My polyline is yellow, shape area is red, the area can't be dragged by mouse is pointed out by black lines.
          alt text

          I also attached my code here.

          def shape(self):
          
              selectionOffset = 15
          
              path = QPainterPath()
          
              pn = [p for p in self._polyline]
          
          
              for k in range(0, len(pn) -1):
                  line = QLineF(pn[k], pn[k+1])
                  radAngle = line.angle()* math.pi / 180
          
                  dx = selectionOffset * math.sin(radAngle)
                  dy = selectionOffset * math.cos(radAngle)
          
                  offset1 = QPointF(dx, dy)
                  offset2 = QPointF(-dx, -dy)
          
                  rect_p1 = line.p1() + offset1
                  rect_p2 = line.p1() + offset2
                  rect_p3 = line.p2() + offset2
                  rect_p4 = line.p2() + offset1
          
                  polygon_new = QPolygonF([rect_p1, rect_p2, rect_p3, rect_p4])
          
                  path.addPolygon(polygon_new)
          
              for m in range(0, len(pn)):
                  path.addEllipse(pn[m], 15, 15)
          
              return path
          
          raven-worxR 1 Reply Last reply
          0
          • H helloworld12345

            @raven-worx
            you can see I drew a rect for each line session, an ellipse for each point(rect doesn't cover the point). With all these rects and ellipses, the polyline is covered totally.

            But at the left-most, right-most, up-most, bottom-most area of the shape, my mouse can't drag the polyline. And at the intersection area of rect and ellipse, I can't drag either, does any one have idea?

            In paint function, I draw my shape area, please see below picture. My polyline is yellow, shape area is red, the area can't be dragged by mouse is pointed out by black lines.
            alt text

            I also attached my code here.

            def shape(self):
            
                selectionOffset = 15
            
                path = QPainterPath()
            
                pn = [p for p in self._polyline]
            
            
                for k in range(0, len(pn) -1):
                    line = QLineF(pn[k], pn[k+1])
                    radAngle = line.angle()* math.pi / 180
            
                    dx = selectionOffset * math.sin(radAngle)
                    dy = selectionOffset * math.cos(radAngle)
            
                    offset1 = QPointF(dx, dy)
                    offset2 = QPointF(-dx, -dy)
            
                    rect_p1 = line.p1() + offset1
                    rect_p2 = line.p1() + offset2
                    rect_p3 = line.p2() + offset2
                    rect_p4 = line.p2() + offset1
            
                    polygon_new = QPolygonF([rect_p1, rect_p2, rect_p3, rect_p4])
            
                    path.addPolygon(polygon_new)
            
                for m in range(0, len(pn)):
                    path.addEllipse(pn[m], 15, 15)
            
                return path
            
            raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on last edited by
            #6

            @helloworld12345
            try setting the fillRule of the path to Qt::WindingFill

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            H 1 Reply Last reply
            1
            • A Offline
              A Offline
              Asperamanca
              wrote on last edited by
              #7

              I would try this:

              • Find out the coordinates of a point which should work for dragging, but doesn't
              • Make a debug function that calls yourPolyline->contains(thatPoint)
              • Step into the contains method and see where the code decides that the point is not part of your polyline's shape
              H 1 Reply Last reply
              1
              • raven-worxR raven-worx

                @helloworld12345
                try setting the fillRule of the path to Qt::WindingFill

                H Offline
                H Offline
                helloworld12345
                wrote on last edited by
                #8

                @raven-worx

                I think I found the root cause, at the beginning I thought shape() function will totally override boundingRect(). But it turns out boundingRect() still functions even I used shape(). When shape() area is out of the area of boundingRect(), the extra part from shape() that if out of the region of boundingRect() will be detected.

                Then I enlarge the the area of boundingRect() to make sure it is larger than shape() area, then it seems good now.

                Does it make sense to you?

                1 Reply Last reply
                0
                • A Asperamanca

                  I would try this:

                  • Find out the coordinates of a point which should work for dragging, but doesn't
                  • Make a debug function that calls yourPolyline->contains(thatPoint)
                  • Step into the contains method and see where the code decides that the point is not part of your polyline's shape
                  H Offline
                  H Offline
                  helloworld12345
                  wrote on last edited by
                  #9

                  @Asperamanca

                  Hi, this is what I replied to raven-worx, does it make sense to you?

                  I think I found the root cause, at the beginning I thought shape() function will totally override boundingRect(). But it turns out boundingRect() still functions even I used shape(). When shape() area is out of the area of boundingRect(), the extra part from shape() that if out of the region of boundingRect() will be detected.

                  Then I enlarge the the area of boundingRect() to make sure it is larger than shape() area, then it seems good now.

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    Asperamanca
                    wrote on last edited by
                    #10

                    The docs nowhere specify that the shape has to be fully contained within the boundingRect. However, it seems like a logical optimization to first make a hit test using the boundingRect, before even checking the much more complex shape.

                    Do you have any clipping flags set (e.g. ItemClipsToShape, or ItemClipsChildrenToShape for a parent)? This might actually change the behavior, because this code of QGraphicsItem seems relevant:

                    bool QGraphicsItem::contains(const QPointF &point) const
                    {
                        return isClipped() ? clipPath().contains(point) : shape().contains(point);
                    }
                    

                    ...and the clipPath() starts with the boundingRect()

                    H 1 Reply Last reply
                    0
                    • A Asperamanca

                      The docs nowhere specify that the shape has to be fully contained within the boundingRect. However, it seems like a logical optimization to first make a hit test using the boundingRect, before even checking the much more complex shape.

                      Do you have any clipping flags set (e.g. ItemClipsToShape, or ItemClipsChildrenToShape for a parent)? This might actually change the behavior, because this code of QGraphicsItem seems relevant:

                      bool QGraphicsItem::contains(const QPointF &point) const
                      {
                          return isClipped() ? clipPath().contains(point) : shape().contains(point);
                      }
                      

                      ...and the clipPath() starts with the boundingRect()

                      H Offline
                      H Offline
                      helloworld12345
                      wrote on last edited by
                      #11

                      @Asperamanca

                      No, I didn't set these two flags ItemClipsToShape, ItemClipsChildrenToShape.

                      Then I tried setting only one flag ItemClipsToShape, and both of ItemClipsToShape, ItemClipsChildrenToShape. For each, it still check if the point is in the boundingrect() firstly, and then check the shape() which means if point is not in boundingrect(), it wouldn't bother to check shape().

                      So now my solution is still enlarging the boundingrect() area.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved