Results 1 to 8 of 8

Thread: Selection of Cubic QPainterPath

  1. #1
    Join Date
    Jul 2014
    Posts
    14
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Selection of Cubic QPainterPath

    Hello,

    I have qgraphicspathitem which is a cubic QPainterPath.
    It is selectable with the mouse by clicking on it.
    The problem is the path is selected when clicking anywhere on the red area in the image (so the shape is "closed" by connecting the start and end directly it seems), not only when clicking on the path directly.
    painterpath1.pngpainterpath2.png
    I reimplemented the qgraphicspathitem::shape() function and return the exact path that is also drawn.

    I also tried to reimplemented the contains function and calculate it myself, but that one is never called.

    How can I achieve a cubic path, that is only selected when clicking exactly on the path?

    thanks
    veio

  2. #2
    Join Date
    Oct 2014
    Posts
    81
    Thanks
    20
    Thanked 9 Times in 9 Posts
    Qt products
    Qt5
    Platforms
    Windows
    Wiki edits
    7

    Default Re: Selection of Cubic QPainterPath

    What I'd do is internally use a QPolygonF shape to represent a 'hull' around the cubic Bézier segment.
    QPolygonF has a 'containsPoint' function that you can return from within the 'contains' function of your custom graphics item.

    By using a specific polygonal hull thickness (so the Bézier segment feels like it has a selectable thickness) and the winding-fill hit test mode of 'containsPoint' you can ensure that only the curve body is selectable. Just make sure to use an odd number of segments in the polygonal hull so the middle segment falls on the cusp point of the Bézier. In case you don't understand what I mean, play with the demo at the "Subdivision in Action" section of the following article; only an odd number of divisions accounts for the middle point in a cusp-style Bézier segment:
    http://ciechanowski.me/blog/2014/02/...bezier-curves/

    EDIT: In order to build the polygonal hull, use the pointAtPercent function of your Qt path to create a set of QPoints from the Bézier segment representing a poly line, that you then use to construct the polygonal hull based on the direction of each line and the desired thickness (at each end point you create a hull division etc.). If you don't understand this, let me know and I'll make a diagram, although that article has something similar in section "Adding Width."
    Obviously you'll cache this polygonal shape and only recompute it after the user creates a new Bézier segment or modifies an existing one.
    Last edited by Kryzon; 27th June 2015 at 23:29.

  3. #3
    Join Date
    May 2015
    Posts
    6
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Selection of Cubic QPainterPath

    thanks for link advice

  4. #4
    Join Date
    Oct 2014
    Posts
    81
    Thanks
    20
    Thanked 9 Times in 9 Posts
    Qt products
    Qt5
    Platforms
    Windows
    Wiki edits
    7

    Default Re: Selection of Cubic QPainterPath

    Another solution is to do a distance check between the point in question and the polyline representing the Bézier segment, all of this from within function 'contains'.
    If the distance of the point to the polyline is less than the thickness you wish to give to the Bézier segment, then the point is contained.

    It's a simpler solution, and faster if you use a squared thickness in the distance comparison. You wouldn't need a square root in the distance check this way, I believe.
    Eleven segments in the polyline (remember the odd number) should be enough to accurately represent a single cubic Bézier segment.

  5. #5
    Join Date
    Jul 2014
    Posts
    14
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Selection of Cubic QPainterPath

    Quote Originally Posted by Kryzon View Post
    Another solution is to do a distance check between the point in question and the polyline representing the Bézier segment, all of this from within function 'contains'.
    If the distance of the point to the polyline is less than the thickness you wish to give to the Bézier segment, then the point is contained.

    It's a simpler solution, and faster if you use a squared thickness in the distance comparison. You wouldn't need a square root in the distance check this way, I believe.
    Eleven segments in the polyline (remember the odd number) should be enough to accurately represent a single cubic Bézier segment.
    I tried reimplementing the contains function of QGraphicsPathItem but it was never called.
    In there I sampled the path QPainterPath:ointAtPercent() at 5% steps.

    Why might it never be called?

    I'll try the hull approach later. Thanks for your input.

  6. #6
    Join Date
    Oct 2014
    Posts
    81
    Thanks
    20
    Thanked 9 Times in 9 Posts
    Qt products
    Qt5
    Platforms
    Windows
    Wiki edits
    7

    Default Re: Selection of Cubic QPainterPath

    I'm not sure why, maybe it's not being overridden properly in your subclass declaration.

  7. #7
    Join Date
    Jul 2014
    Posts
    14
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Selection of Cubic QPainterPath

    I tried that with the hull and it works like a charm. Thank you.

    @contains() not called: According to this thread the doc is just not really clear and contains is not called by the qt framework itself.

  8. #8
    Join Date
    Oct 2014
    Posts
    81
    Thanks
    20
    Thanked 9 Times in 9 Posts
    Qt products
    Qt5
    Platforms
    Windows
    Wiki edits
    7

    Default Re: Selection of Cubic QPainterPath

    Thank you for sharing, I'll have to deal with path selection later as well.
    According to that thread what the documentation means is that 'contains' is called by you, manually, when you want to know if the item contains a point.

    After digging through the source, it seems that mouse selection is done when QGraphicsView receives user events (mouse clicks etc.), sends analogous events to QGraphicsScene and the scene then does the item shape test with QGraphicsItem::collidesWithPath with a "point rectangle" (a one-pixel rectangle).
    So the important part is providing an adequate path in the 'shape' function of your graphics item, like that hull or a path outline generated by QPainterPathStroker

Similar Threads

  1. QPainterPath
    By Karl123 in forum Newbie
    Replies: 2
    Last Post: 16th June 2013, 17:26
  2. QPainterPath -
    By aguleo in forum Newbie
    Replies: 4
    Last Post: 17th February 2013, 17:47
  3. Problem with QPainterPath
    By kaktus123 in forum Qt Programming
    Replies: 0
    Last Post: 7th August 2012, 13:10
  4. QPainterPath::quadTo(...) calls QPainterPath::cubicTo(...) ?
    By brucelamond in forum Qt Programming
    Replies: 0
    Last Post: 29th April 2011, 00:30
  5. QPainterPath outlining
    By viridis in forum Qt Programming
    Replies: 2
    Last Post: 14th March 2008, 20:32

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.