c++ - Qt design and performance issue -
i having troubles while designing c++ qt application. among other things, application displays beams (or rays) of lasers (each laser composed around 700 segments starting same position , spaced constant angle, , small circle @ other end of segment materializing end point). here drafting of 1 laser found on internet . of time have display 12 lasers (so 12*700 segments), @ 30 frames per second. first implementation works, takes huge amount of cpu (>12%) , gui lags lot.
what did implementation quite simple: have lasermodel
class, filled thread receiving tcp beacons; mainwindow
class qgraphicsscene* _scene
; , laserview
class, instances added scene. signal @ 30fps triggers passage of datas model view using setdata()
method.
i did performance analysis , seems 80% of work of gui (there way more displaying these lasers) done drawline(/*…*/)
methods.
i sure there more elegant , efficient way that.
first
setdata(/*…*/)
method seems quite ugly me. know should emit signal (likelaserhaschanged(const lasermodel&))
model , catch in view (with slotonnewdata(const lasermodel&)
) performance point of view seems worse (but looks better coupling point of view, because in future display property tree configuration of lasers(so view of same model)).more important not quite sure
drawline(const qline& line)
does, part of code should “render” line, not recreate it.
so question is: how can drastically improve performances of rendering? drawline part of paint() method?
here relevant code:
class laserview : public qgraphicsitem { /* c-tor, d-tor, members... */ std::vector<beam> _beams; qrectf _boundingrect; void setdata(const sim::pose& pose, const std::vector<beam>& beams, const qrectf& boundingrect, const bool& showmaxranges) { /*...*/ _beams = beams; _boundingrect = boundingrect; } void paint(qpainter *painter, const qstyleoptiongraphicsitem *option, qwidget *) { painter->setpen(_color); // display beams stopped obstacle if (!_showmaxranges) { (unsigned int = 0 ; < _beams.size() -1 ; i++) { if (!_beams[i].endpointtype == laserbeamendpointtype::max_range) { _beams[i]._line.setline(_pose.x, _pose.y, _beams[i]._mapendpose.x(), _beams[i]._mapendpose.y()); painter->drawline(_beams[i]._line); } } } // display beams else { (unsigned int = 0 ; < _beams.size() -1 ; i++) { _beams[i]._line.setline(_pose.x, _pose.y, _beams[i]._mapendpose.x(), _beams[i]._mapendpose.y()); painter->drawline(_beams[i]._line); } } // draw small circle visualize end points of beams when stop against obstacle (unsigned int = 0; < _beams.size() - 1 ; i++) { // draw end point in blue if obstacle reflective if (_beams[i].endpointtype == laserbeamendpointtype::reflective_object) { painter->setbrush(refletive_end_point_color); painter->drawellipse(_beams[i]._mapendpose, end_point_size, end_point_size); } // draw end point in red if obstacle not reflective else if (_beams[i].endpointtype == laserbeamendpointtype::not_reflective_object) { painter->setbrush(not_refletive_end_point_color); painter->drawellipse(_beams[i]._mapendpose, end_point_size, end_point_size); } } }
}
you drawing 1 line @ time, 1 ellipse @ time, switching between brushes in process. there significant overhead these operations (at least qt4). can better aggregating these calls 3 drawing calls.
you have
std::vector<qlinef> lines; std::vector<qrectf> ellipse_refl_rects; std::vector<qrectf> ellipse_non_refl_rects;
rather drawing line add lines
collection. same ellipses. @ end have
if(!lines.isempty()) { painter->drawlines(&lines[0], lines.size()); } if(!ellipse_refl_rects.isempty()) { painter->setbrush(refletive_end_point_color); painter->drawellipses(&ellipse_refl_rects[0], ellipse_refl_rects.size()); } if(!ellipse_non_refl_rects.isempty()) { painter->setbrush(not_refletive_end_point_color); painter->drawellipses(&ellipse_non_refl_rects[0], ellipse_non_refl_rects.size()); }
Comments
Post a Comment