Results 1 to 5 of 5

Thread: Curve through points

  1. #1
    Join Date
    Jan 2019
    Posts
    2
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Curve through points

    Hey,
    I'm new to posting on the forum but I've used it a lot.

    I have an issue that I cant seem to find an answer on though.

    My problem is that I have a number of points on a QGraphicsScene that are movable.

    I want to be able to draw a curve that will pass through them. The thing is that the number of points is dynamic, can be 3 to a much larger number.
    I have tried a QPainterPath, but I can only get straight lines between them.

    I feel that someone will mention Bezier curves but I tried them. Unfortunately, it wont work for a couple of reasons:
    1. The control point is not on the curve.
    2. The curve will need to be more than one curve, it could be multiple "S" shapes strung together.

    My attempt is below, I could be missing a flag from the QPainterPath to put a curve between the points but I'm struggling to find it:

    Qt Code:
    1. QVector<QPointF> points;
    2. points << startPoint;
    3. for (int i=0; i<mHandles.size(); i++) {
    4. points << mHandles.at(i)->scenePos();
    5. }
    6. points << endPoint;
    7.  
    8. QPainterPath testCurve;
    9.  
    10. testCurve.addPolygon(QPolygonF(points));
    11. painter->drawPath(testCurve);
    To copy to clipboard, switch view to plain text mode 

    Any help would be greatly appreciated,
    Thanks in advance

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    3,871
    Thanks
    224
    Thanked 601 Times in 591 Posts
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: Curve through points

    You want a "piecewise cubic spline". Google for "piecewise cubic spline C++" and you'll see several implementations. This type of spline interpolates between the control points using a cubic polynomial, with the conditions that the control points lie on the line and the slope of the two segments on either side of the control point is continuous. Thus you get a smooth curve that passes through each of the control points.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,123
    Thanked 811 Times in 760 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Curve through points

    If you are looking for an implementation for Qt you can have a look at Qwt. You have to use a branch >= 6.2 ( f.e https://svn.code.sf.net/p/qwt/code/trunk/qwt ) - I have replaced the broken spline implementation from 6.1 and added implementations for many spline interpolation algos, that looked relevant to me.

    In playground/splineeditor you find an example, where you can play with the various algos and their parameters to see their effect.

    Note that a cubic polynomial is different way to describe a Bezier curve and with the Qwt spline classes you can create a list of polynomials or bezier curves. So you could feed the QwtSpline classes with your points and use the calculated QPainterPath ( what is a sequence of bezier curves in this case ).

    HTH,
    Uwe
    Last edited by Uwe; 12th January 2019 at 15:18.

  4. The following user says thank you to Uwe for this useful post:

    barry2310 (14th January 2019)

  5. #4
    Join Date
    Jan 2019
    Posts
    2
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Curve through points

    Thanks for the replies guys.

    I went with the Qwt 6.2 option.

    I implemented the QwtSplineCurveFitter and I have what I want.

    Here is my implementation for anyone who has this issue:

    Qt Code:
    1. QVector<QPointF> points;
    2. points << startPoint;
    3. for (int i=0; i<mHandles.size(); i++) {
    4. points << mHandles.at(i)->scenePos();
    5. }
    6. points << endPoint;
    7.  
    8. QPainterPath testCurve;
    9.  
    10. QwtSplineCurveFitter curveFitter;
    11. testCurve = curveFitter.fitCurvePath(QPolygonF(points));
    12. painter->drawPath(testCurve);
    To copy to clipboard, switch view to plain text mode 

    Uwe, thank you so much for this! I had been trying to come up with a solution for a long time!

    - Barry

  6. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,123
    Thanked 811 Times in 760 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Curve through points

    Note that QwtSplineCurveFitter is only a wrapper around the actual QwtSpline classes, that you don't need in your case.

    The default implementation of QwtSplineCurveFitter uses a parametric cardinal spline with a uniform parametrization. In case you have specific requirements ( like performance ) it might be worth to find the right spline interpolation/approximation options for you. F.e when your curve has increasing x or y values you don't need parametrization and could go with ParameterX/ParameterY ( = no parametrization ) instead.

    ( Parametrization is always doing things twice: x = f(t) and y = g(t) instead of y = f(x) )

    Uwe

Similar Threads

  1. number of visible points of a curve
    By HappyCoder in forum Qwt
    Replies: 1
    Last Post: 31st May 2016, 09:54
  2. Curve could not pass the points
    By momo in forum Qwt
    Replies: 4
    Last Post: 19th February 2014, 02:08
  3. Replies: 0
    Last Post: 28th August 2013, 12:38
  4. Replies: 2
    Last Post: 4th September 2011, 22:50
  5. Get the points of a fitted curve
    By giusepped in forum Qwt
    Replies: 4
    Last Post: 25th December 2008, 08:42

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.