[Interest] best qt class to use to detect line/polygon/region collision

Henry Skoglund fromqt at tungware.se
Tue Aug 9 02:32:30 CEST 2016


On 2016-08-08 18:05, maitai wrote:
> Hello all,
>
> I have a list of lines (QLineF) in 2D space. Some might represent a
> closed polygon, some others are just a line or represent a non closed
> polygon. Classical problem: I need to detect if another given line is
> crossing one of the lines in the list. I don't need the crossing point,
> just to know if it crosses or not.
>
> For the time being, I just iterate on the list and use
> QLineF::intersects(). This is of course badly slow.
>
> I read that post (and many others):
> http://stackoverflow.com/questions/9393672/intersection-point-of-qpainterpath-and-line-find-qpainterpath-y-by-x
>
>
> Using a QPainterPath seems the right idea, but as it seems it does not
> work with a single line, so maybe I should convert the line in a tiny
> rectangle to be able to use QPainterPath::intersects(). Will that be
> faster?
>
> Before I try that, I was wondering if someone has a better idea as of
> what class to use in qt to solve this? Calculation speed is the most
> important thing in my case.
>
> Thanks for pointing me in the right direction
> Philippe Lelong

Isn't this some kind of sorting problem in disguise? You could try 
sorting the coords of the lines in your list to speed up the processing. 
I made a simple example using a QMap:
---------------------------------------------------------------------
// make list of QLineFs
     QList<QLineF> lLines;
     for (int i = 0; (i < 1000000); ++i)
     {
         QLineF l(rand() / 100.0,rand() / 100.0,rand() / 100.0,rand() / 
100.0);

     // make sure dx is positive (x1 <= x2)
         if (l.x1() > l.x2())
         // if not swap the points
             l = QLineF(l.p2(),l.p1());

         lLines.append(l);
     }

// insert all x1 coords (and their position in the list) in a map
     QMap<qreal,int> mx1;
     for (int i = 0; (i < lLines.count()); ++i)
         mx1.insertMulti(lLines[i].x1(),i);

// make another list of QLineFs to test with
     QList<QLineF> lTest;
     for (int i = 0; (i < 20); ++i)
     {
         QLineF l(rand() / 100.0,rand() / 100.0,rand() / 100.0,rand() / 
100.0);

     // make sure dx is positive (x1 <= x2)
         if (l.x1() > l.x2())
         // if not swap the points
             l = QLineF(l.p2(),l.p1());

         lTest.append(l);
     }

// test simple way
     int crossings1 = 0;
     for (auto t : lTest)
         for (auto l : lLines)
             if (QLineF::BoundedIntersection == l.intersect(t,nullptr))
                 ++crossings1;

// test with map
     int crossings2 = 0;
     for (auto t : lTest)
     {
         auto iUpper = mx1.upperBound(t.x2());
         auto i = mx1.begin();
         while (i != iUpper)
         {
             auto l = lLines[i.value()];
             if (QLineF::BoundedIntersection == l.intersect(t,nullptr))
                 ++crossings2;

             ++i;
         }
     }

// crossings1 == crossings2
---------------------------------------------------------------------

Random access in the list from the values in QMap well not yield so good 
performance, the QlineFs should be stored in a vector instead.

Perhaps a next step could be to do a similar QMap sorting of the .x2() 
coords and do a .lowerbound(t.x1()) stepping down and then also sort the 
y coords. But I need more coffee to understand that right now..

Rgrds Henry





More information about the Interest mailing list