void Private::SearchSequence(
    SeqIter					seq_cur,
    SeqIter					seq_end,
    ExpIter					exp_cur,
    ExpIter					exp_end,
    IdSetTable	const &		set_table,
    QVector<QModelIndex> &  path,
    QIdxSequence &          rv)
{   // TODO: optimized by dynamic programming.
    if (exp_cur == exp_end) {
        rv.push_back(path);
        return;
    }

    if (seq_cur == seq_end)
        return;

    SeqIter seq_nxt		= std::next(seq_cur);
    ExpIter exp_nxt		= std::next(exp_cur);
    auto & caller_set	= set_table[exp_cur->first];
    auto & callee_set	= set_table[exp_cur->second];
    auto & caller       = *seq_cur->first;
    auto & callee       = *seq_cur->second;

    if (caller_set.find(caller.id) != caller_set.end() &&
            callee_set.find(callee.id) != callee_set.end()) {
        path.push_back(caller.item->index());
        path.push_back(callee.item->index());
        SearchSequence(seq_nxt, seq_end, exp_nxt, exp_end, set_table, path, rv);
        path.pop_back();
        path.pop_back();
    }

    SearchSequence(seq_nxt, seq_end, exp_cur, exp_end, set_table, path, rv);
}
void LivewireCalculator::DrawTrace(uint x, uint y, QPainter &g) const
{
	const uint w = this->_weights->GetReducedWidth(), scale = this->_weights->GetScale(), s2 = scale / 2;
	if (this->_visited.Get(x /= scale, y /= scale)) // The endpoint has been solved, so we can actually draw the livewire
	{
		// Get every point from end to start by looping through the trace data
		QVector<QPoint> pts;
		uint I = x + y * w;
		do
		{
			QPoint p = QPoint((x = I % w) * scale + s2, (y = I / w) * scale + s2);
			pts.push_back(p);
			pts.push_back(p);
		}
		while ((I = this->_trace.Get(x, y)) != UINT_MAX);

		// Draw the points
		if (pts.size() >= 4)
		{
			pts.pop_back();
			pts.pop_front();
			g.drawLines(pts);
		}
	}
}
Ejemplo n.º 3
0
void fonctionsCommunes::Optim(QVector<Triangle> &triangles, QVector<QPointF> &points, QVector<QPoint> &pile)
{


    while (!pile.isEmpty()){
        QPoint f = pile[pile.size()-1] ;
        int x = f.x() ;
        int y = f.y() ;
        qDebug() << "pile " << x << y ;
        pile.pop_back();
        int idNonCommun = triangles[y].nonCommun(x) ; //chercher l'indice du point de f.y non commun avec f.x
        qDebug() << idNonCommun << ": idNonCommun";
        if ( (idNonCommun>0) && ((triangles[x].trouverVoisinSachantId(y)) >= 0 ) && ((triangles[y].trouverVoisinSachantId(x))>=0) )   {
            qDebug( ) << "swaping " << f.x() << f.y() ;

            if (triangles[x].inCircle( idNonCommun , points )){
                fonctionsCommunes::Swap(f.x() , f.y(), points ,triangles , pile ) ;
            }

        }

    }


}
Ejemplo n.º 4
0
QVector< int > Logger::polygonEndpointsTracklog()
{
	QVector<int> endpoints;
	bool append = false;
	int invalidElements = 0;
	for (int i = 0; i < m_gpsInfoBuffer.size(); i++)
	{
		if( !m_gpsInfoBuffer.at(i).position.IsValid() )
		{
			invalidElements++;
			append = true;
			continue;
		}
		if (append == true || endpoints.size() == 0)
		{
			endpoints.append(i+1-invalidElements);
			append = false;
			continue;
		}
		endpoints.pop_back();
		endpoints.append(i+1-invalidElements);
	}

	return endpoints;
}
Ejemplo n.º 5
0
void GwfStreamWriter::writePair(SCgObject *obj)
{
    QString type = mTypeAlias2GWFType[obj->typeAlias()].mid(0,3);
    if(type=="arc")
        writeStartElement(type);
    else
        writeStartElement("pair");
    writeObjectAttributes(obj);
    SCgPair* pair = static_cast<SCgPair*>(obj);
    SCgObject* b = pair->getBeginObject();
    SCgObject* e = pair->getEndObject();
    writeAttribute("id_b", QString::number(b->id()));
    writeAttribute("id_e", QString::number(e->id()));

    writePosition(b,"b_x","b_y");
    writePosition(e,"e_x","e_y");

    writeAttribute("dotBBalance", QString::number(pair->getBeginDot()));
    writeAttribute("dotEBalance", QString::number(pair->getEndDot()));
    QVector<QPointF> points = pair->scenePoints();
    points.pop_back();
    points.pop_front();
    writePoints(points);
    writeEndElement();
}
Ejemplo n.º 6
0
 void run() {
     AVThread *avt = demux_thread->videoThread();
     avt->packetQueue()->clear(); // clear here
     if (pts <= 0) {
         demux_thread->demuxer->seek(qint64(-pts*1000.0) - 500LL);
         QVector<qreal> ts;
         qreal t = -1.0;
         while (t < -pts) {
             demux_thread->demuxer->readFrame();
             if (demux_thread->demuxer->stream() != demux_thread->demuxer->videoStream())
                 continue;
             t = demux_thread->demuxer->packet().pts;
             ts.push_back(t);
         }
         const qreal t0 = ts.back();
         ts.pop_back();
         const qreal dt = t0 - ts.back();
         pts = ts.back();
         // FIXME: sometimes can not seek to the previous pts, the result pts is always current pts, so let the target pts a little earlier
         pts -= dt/2.0;
     }
     qDebug("step backward: %lld, %f", qint64(pts*1000.0), pts);
     demux_thread->video_thread->setDropFrameOnSeek(false);
     demux_thread->seekInternal(qint64(pts*1000.0), AccurateSeek);
 }
Ejemplo n.º 7
0
/** Returns a list of points on the bandwidth graph based on the supplied set
 * of rsdht or alldht values. */
void RSGraphWidget::pointsFromData(const std::vector<QPointF>& values,QVector<QPointF>& points)
{
    points.clear();

    int x = _rec.width();
    int y = _rec.height();

    float time_step = 1.0f ;	// number of seconds per pixel

    /* Translate all data points to points on the graph frame */

    // take 0 as the origin, otherwise the different curves are not aligned properly
    float last = 0;//values.back().x();

    //std::cerr << "Got " << values.size() << " values for index 0" << std::endl;

    float last_px = SCALE_WIDTH ;
    float last_py = 0.0f ;

    for (uint i = 0; i < values.size(); ++i)
	 {
		 //std::cerr << "Value: (" << values[i].x() << " , " << values[i].y() << ")" << std::endl;

		 // compute point in pixels

		 qreal px = x - (values[i].x()-last)*_time_scale ;
		 qreal py = y -  valueToPixels(values[i].y()) ;

		 if(px >= SCALE_WIDTH && last_px < SCALE_WIDTH)
		 {
			 float alpha = (SCALE_WIDTH - last_px)/(px - last_px) ;
			 float ipx = SCALE_WIDTH ;
			 float ipy = (1-alpha)*last_py + alpha*py ;

			 points << QPointF(ipx,y) ;
			 points << QPointF(ipx,ipy) ;
		 }
		 else if(i==0)
			 points << QPointF(px,y) ;

		 last_px = px ;
		 last_py = py ;

		 if(px < SCALE_WIDTH)
			 continue ;

		 _maxValue = std::max(_maxValue,values[i].y()) ;

		 // remove midle point when 3 consecutive points have the same value.

		 if(points.size() > 1 && points[points.size()-2].y() == points.back().y() && points.back().y() == py)
			 points.pop_back() ;

		 points << QPointF(px,py) ;

		 if(i==values.size()-1)
			 points << QPointF(px,y) ;
	 }
}
Ejemplo n.º 8
0
void PaintWidget::waypointsChanged()
{
	m_request.target = RoutingLogic::instance()->target();
	QVector< UnsignedCoordinate > waypoints = RoutingLogic::instance()->waypoints();
	if ( waypoints.size() > 0 && RoutingLogic::instance()->target() == waypoints.back() )
		waypoints.pop_back();
	m_request.waypoints = waypoints;
	update();
}
Ejemplo n.º 9
0
QPair<T, T> confint(const QVector<T> &vecin) {
	long double avg = 0.0;
	long double stddev = 0.0;
	QVector<T> vec = vecin;
	qSort(vec.begin(), vec.end());
	for (int i=0;i<vec.count() / 20;++i) {
		vec.pop_front();
		vec.pop_back();
	}

	foreach(T v, vec)
		avg += v;
	avg /= vec.count();

	foreach(T v, vec)
		stddev += (v-avg)*(v-avg);
	stddev = sqrtl(stddev / vec.count());
	return QPair<T,T>(static_cast<T>(avg), static_cast<T>(1.96 * stddev));
}
Ejemplo n.º 10
0
void ProfilesWindow::onMenuSelection(QAction *menuAction)
{
    QString id = menuAction->data().toString();

    QVector<int> checkedItems;
    for (int i = 0; i<ui->listWidgetProfiles->count(); i++){
        QListWidgetItem* item = ui->listWidgetProfiles->item(i);
        if (item->checkState()==Qt::Checked)
            checkedItems.push_back(item->data(Qt::UserRole).toInt());
    }

    if (id=="NEW_PROFILE"){
        m_DataManager->addNewProfile(tr("New Profile"));
        rebuild();
        return;
    }

    if (id=="CLONE_PROFILE"){
        if (checkedItems.size()!=1){
            QMessageBox::critical(this,tr("Incorrect arguments"),tr("Please select one and only one profile for cloning"),QMessageBox::Ok);
            return;
        }
        int index = checkedItems[0];
        m_DataManager->addNewProfile(m_DataManager->profiles(index)->name+" "+tr("copy"),index);
        rebuild();
        return;
    }

    if (id=="MERGE_PROFILES"){
        if (checkedItems.size()<2){
            QMessageBox::critical(this,tr("Incorrect arguments"),tr("Please select at least two profiles for merging"),QMessageBox::Ok);
            return;
        }
        if (QMessageBox::warning(this,tr("Data will be lost"),tr("Warning! After the merging uniqe difference between profiles will be lost. This operation can't be undone. Proceed?"),QMessageBox::Yes,QMessageBox::Cancel)==QMessageBox::Yes){
            while (checkedItems.size()>1){
                m_DataManager->mergeProfiles(checkedItems[checkedItems.size()-2],checkedItems[checkedItems.size()-1]);
                checkedItems.pop_back();
            }
            rebuild();
        }
        return;
    }
}
Ejemplo n.º 11
0
void GwfStreamWriter::writeBus(SCgObject *obj)
{
    writeStartElement("bus");
    writeObjectAttributes(obj);
    SCgBus* bus = static_cast<SCgBus*>(obj);

    writeAttribute("owner", QString::number(bus->owner()->id()));

    QVector<QPointF> points = bus->scenePoints();
    writeAttribute("b_x", QString::number(points.first().x()));
    writeAttribute("b_y", QString::number(points.first().y()));
    writeAttribute("e_x", QString::number(points.last().x()));
    writeAttribute("e_y", QString::number(points.last().y()));

    // do not save begin and end points
    points.pop_back();
    points.pop_front();
    writePoints(points);

    writeEndElement();
}
Ejemplo n.º 12
0
//# if constant-expression newline group[opt]
bool Preprocessor::parseIfLikeDirective(IfLikeDirective *node)
{
    //cout << "parse if-like directive" << endl;
    Q_ASSERT(node->toItemComposite());
    TokenSection tokenSection = readLine();
    QVector<int> cleanedSection = cleanTokenRange(tokenSection);
    if(cleanedSection.count() < 3)
        return false;

    cleanedSection.erase(cleanedSection.begin(), cleanedSection.begin() + 2); //remove # and if
    cleanedSection.pop_back(); //remove endl;

    const TokenList sectionList(m_tokenContainer, cleanedSection);
    ExpressionBuilder expressionBuilder(sectionList, m_tokenTypeList, m_memoryPool);
    Expression *expr = expressionBuilder.parse();
    node->setTokenSection(tokenSection);
    node->setExpression(expr);

    parseGroup(node);
    return true;
}
Ejemplo n.º 13
0
void Tree::builtRep(Node * SubTree , QVector<bool> Rep )
{
    //SubTree->ShowNode();
    if( SubTree->isLeaf() )
    {
        Code.insert( SubTree->getChar(), Rep );
        if(SubTree->getChar() == '*' )
            this->Represent += "!*";
        else if( SubTree->getChar() == '!' )
            this->Represent += "!!";
        else
            this->Represent += SubTree->getChar();
    }
    else
    {
        this->Represent += "*";
        Rep.push_back(0);
        builtRep(SubTree->getNodeLeft(),  Rep);
        Rep.pop_back();
        Rep.push_back(1);
        builtRep(SubTree->getNodeRight(),Rep );
    }
}
Ejemplo n.º 14
0
void RGBMatrix::updateMapChannels(const RGBMap& map, const FixtureGroup* grp)
{
    uint fadeTime = (overrideFadeInSpeed() == defaultSpeed()) ? fadeInSpeed() : overrideFadeInSpeed();

    // Create/modify fade channels for ALL pixels in the color map.
    for (int y = 0; y < map.size(); y++)
    {
        for (int x = 0; x < map[y].size(); x++)
        {
            QLCPoint pt(x, y);
            GroupHead grpHead(grp->head(pt));
            Fixture* fxi = doc()->fixture(grpHead.fxi);
            if (fxi == NULL)
                continue;

            QLCFixtureHead head = fxi->head(grpHead.head);

            QVector <quint32> rgb = head.rgbChannels();
            QVector <quint32> cmy = head.cmyChannels();

            quint32 masterDim = fxi->masterIntensityChannel();
            quint32 headDim = head.channelNumber(QLCChannel::Intensity, QLCChannel::MSB);

            // Collect all dimmers that affect current head:
            // They are the master dimmer (affects whole fixture)
            // and per-head dimmer.
            //
            // If there are no RGB or CMY channels, the least important* dimmer channel
            // is used to create grayscale image.
            //
            // The rest of the dimmer channels are set to full if dimmer control is
            // enabled and target color is > 0 (see
            // http://www.qlcplus.org/forum/viewtopic.php?f=29&t=11090)
            //
            // Note: If there is only one head, and only one dimmer channel,
            // make it a master dimmer in fixture definition.
            //
            // *least important - per head dimmer if present,
            // otherwise per fixture dimmer if present
            QVector <quint32> dim;
            if (masterDim != QLCChannel::invalid())
                dim << masterDim;

            if (headDim != QLCChannel::invalid())
                dim << headDim;

            uint col = map[y][x];

            if (rgb.size() == 3)
            {
                // RGB color mixing
                {
                    FadeChannel fc(doc(), grpHead.fxi, rgb.at(0));
                    fc.setTarget(qRed(col));
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }

                {
                    FadeChannel fc(doc(), grpHead.fxi, rgb.at(1));
                    fc.setTarget(qGreen(col));
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }

                {
                    FadeChannel fc(doc(), grpHead.fxi, rgb.at(2));
                    fc.setTarget(qBlue(col));
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }
            }
            else if (cmy.size() == 3)
            {
                // CMY color mixing
                QColor cmyCol(col);

                {
                    FadeChannel fc(doc(), grpHead.fxi, cmy.at(0));
                    fc.setTarget(cmyCol.cyan());
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }

                {
                    FadeChannel fc(doc(), grpHead.fxi, cmy.at(1));
                    fc.setTarget(cmyCol.magenta());
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }

                {
                    FadeChannel fc(doc(), grpHead.fxi, cmy.at(2));
                    fc.setTarget(cmyCol.yellow());
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }
            }
            else if (!dim.empty())
            {
                // Set dimmer to value of the color (e.g. for PARs)
                FadeChannel fc(doc(), grpHead.fxi, dim.last());
                // the weights are taken from
                // https://en.wikipedia.org/wiki/YUV#SDTV_with_BT.601
                fc.setTarget(0.299 * qRed(col) + 0.587 * qGreen(col) + 0.114 * qBlue(col));
                insertStartValues(fc, fadeTime);
                m_fader->add(fc);
                dim.pop_back();
            }

            if (m_dimmerControl)
            {
                // Set the rest of the dimmer channels to full on
                foreach(quint32 ch, dim)
                {
                    FadeChannel fc(doc(), grpHead.fxi, ch);
                    fc.setTarget(col == 0 ? 0 : 255);
                    insertStartValues(fc, fadeTime);
                    m_fader->add(fc);
                }
            }
        }
    }
Ejemplo n.º 15
0
void SCgModeBus::mousePressEvent (QGraphicsSceneMouseEvent * mouseEvent , bool afterSceneEvent)
{
    if(afterSceneEvent)
    {
        if(mDecoratedMode)
            mDecoratedMode->mousePressEvent(mouseEvent, afterSceneEvent);
        return;
    }

    mouseEvent->accept();
    QPointF mousePos = mouseEvent->scenePos();

    if (mPathItem && mouseEvent->button() == Qt::LeftButton)
        mPathItem->pushPoint(mousePos);

    // right button
    if (mouseEvent->button() == Qt::RightButton)
    {
        if (mPathItem)
        {
            mPathItem->popPoint();
            // if there is no points
            if (mPathItem->points().empty())
                delete mPathItem;
            return;
        }
    }

    if (mouseEvent->button() == Qt::LeftButton)
    {
        if (!mPathItem)
        {
            SCgVisualObject *obj = scene()->scgVisualObjectAt(mousePos);
            mNode = (obj != 0 && obj->type() == SCgVisualObject::SCgNodeType) ? static_cast<SCgVisualNode*>(obj) : 0;
            if(mNode)
            {
                mPathItem = new SCgPathItem(scene());
                mPathItem->pushPoint(mNode->scenePos());

                QPen pen;

                pen.setColor(Qt::blue);
                pen.setWidthF(5.f);
                pen.setCapStyle(Qt::RoundCap);
                pen.setStyle(Qt::DashDotLine);

                mPathItem->setPen(pen);
                return;
            }

        }else
        {
            QVector<QPointF> points = mPathItem->points();
            // The last point in points is mousePos, so we should get previous
            QVector2D vec(points.at(points.size() - 2) - mousePos);

            Q_ASSERT(mNode && mNode->baseObject() && mNode->baseObject()->type() == SCgObject::Node);
            if (points.size() > 2 && vec.length() < 5.f)
            {
                points.pop_back();

//                SCgVisualContour* contour = 0;
                // get parent contour
//                QGraphicsItem* parent = mNode->parentItem();

//                if (parent && parent->type() == SCgVisualContour::Type)
//                    contour = static_cast<SCgVisualContour*>(parent);

                scene()->pushCommand(new SCgCommandCreateBus(scene(), static_cast<SCgNode*>(mNode->baseObject()),
                                                                   points, 0));
                delete mPathItem;

                return;
            }
        }
    }

    if(mDecoratedMode)
    {
        mDecoratedMode->mousePressEvent(mouseEvent, afterSceneEvent);
        mPassMouseReleaseEvent = true;
    }
}
Ejemplo n.º 16
0
/*
inline float getAxisElem4( cl_float4 vec, int axis )
{
    if( axis == 0 )
        return vec.x;
    else if( axis == 1 )
        return vec.y;
    else if( axis == 2 )
        return vec.z;
    else
        return -1;
}

bool checkRange( const cl_float4 intersect, const cl_float4 range, const int axis )
{
    bool result = false;
    switch( axis )
    {
    case 0: // X axis range
        if( intersect.y >= range.x && intersect.y <= range.y &&
                intersect.z >= range.z && intersect.z <= range.w )
          result = true;
        break;
    case 1: // Y axis range
        if( intersect.x >= range.x && intersect.x <= range.y &&
                intersect.z >= range.z && intersect.z <= range.w )
          result = true;
        break;
    case 2: // Z axis range
        if( intersect.x >= range.x && intersect.x <= range.y &&
                intersect.y >= range.z && intersect.y <= range.w )
          result = true;
        break;
    default:
        break;
    }
    return result;
}

float dot( cl_float3 f1, cl_float3 f2 )
{
    return f1.x*f2.x + f1.y*f2.y + f1.z*f2.z;
}

float doIntersectPlane( cl_float3 point, cl_float3 norm, cl_float4 eyePos, cl_float4 d)
{

    float t = -1;
    float denominator = (norm.x*d.x+norm.y*d.y+norm.z*d.z);
    if(fabs(denominator)>EPSILON)
    {
        cl_float3 eye3;
        eye3.x  =eyePos.x;
        eye3.y = eyePos.y;
        eye3.z = eyePos.z;
        t = (dot(norm, point)-dot(norm, eye3))/(denominator);
    }

    return t;
}

void doIntersectRayKdBox2(
        const cl_float4 eyePos,
        const cl_float4 d,
        float* near,
        float* far,
        const cl_float3 boxStart,
        const cl_float3 boxSize
    )
{
    *near = -1;
    *far = -1;
    cl_float3 start = boxStart;
    cl_float3 end;
    end .x = boxStart.x + boxSize.x;
    end .y = boxStart.y + boxSize.y;
    end .z = boxStart.z + boxSize.z;

    cl_float3 norm[3];
//    = {(cl_float3)(1,0,0), (cl_float3)(0,1,0), (cl_float3)(0,0,1) };
    norm[0].x = 1, norm[0].y = 0, norm[0].z = 0;
    norm[1].x = 0, norm[1].y = 1, norm[1].z = 0;
    norm[2].x = 0, norm[2].y = 0, norm[2].z = 1;

    cl_float4 range[3];
    range[0].x = start.y, range[0].y = end.y, range[0].z = start.z, range[0].w = end.z;
     range[1].x = start.x, range[1].y = end.x, range[1].z = start.z, range[1].w = end.z;
      range[2].x = start.x, range[2].y = end.x, range[2].z = start.y, range[2].w = end.y;
    float t[6];
    t[0] = doIntersectPlane( start, norm[0], eyePos, d );
    t[1] = doIntersectPlane( end, norm[0], eyePos, d );
    t[2] = doIntersectPlane( start, norm[1], eyePos, d );
    t[3] = doIntersectPlane( end, norm[1], eyePos, d );
    t[4] = doIntersectPlane( start, norm[2], eyePos, d );
    t[5] = doIntersectPlane( end, norm[2], eyePos, d );

    cl_float4 intersectPoint[6];
    float min = POS_INF;
    float max = -POS_INF;
    for( int i = 0; i < 6; i++ )
    {
        intersectPoint[i].x = eyePos.x + t[i]*d.x;
        intersectPoint[i].y = eyePos.y + t[i]*d.y;
        intersectPoint[i].z = eyePos.z + t[i]*d.z;
        intersectPoint[i].w = eyePos.w + t[i]*d.w;
        if( t[i] > 0 && checkRange( intersectPoint[i], range[i/2], i/2 ) && min > t[i] )
        {
            min = t[i];
            *near = t[i];
        }
        if( t[i] > 0 && checkRange( intersectPoint[i], range[i/2], i/2 ) && max < t[i] )
        {
            max = t[i];
            *far = t[i];
        }
    }
}

bool boxContain( const cl_float3 start, const cl_float3 size, const cl_float3 pos )
{
    cl_float3 v1 = start;
    cl_float3 v2;
    v2.x  = start.x  + size.x;
    v2.y  = start.y  + size.y;
    v2.z  = start.z  + size.z;
        return ((pos.x >= v1.x) && (pos.x <= v2.x) &&
                (pos.y >= v1.y) && (pos.y <= v2.y) &&
                (pos.z >= v1.z) && (pos.z <= v2.z));
}

cl_float4 add4( cl_float4 v1, cl_float4 v2 )
{
    cl_float4 result;
    result.x = v1.x + v2.x;
    result.y = v1.y + v2.y;
    result.z = v1.z + v2.z;
    result.w = v1.w + v2.w;
    return result;
}

cl_float3 add3( cl_float3 v1, cl_float3 v2 )
{
    cl_float3 result;
    result.x = v1.x + v2.x;
    result.y = v1.y + v2.y;
    result.z = v1.z + v2.z;
    return result;
}

cl_float3 mult3( float s,  cl_float3 v )
{
    cl_float3 result;
    result.x = s*v.x;
    result.y = s*v.y;
    result.z = s*v.z;
    return result;
}

cl_float4 mult4( float s,  cl_float4 v )
{
    cl_float4 result;
    result.x = s*v.x;
    result.y = s*v.y;
    result.z = s*v.z;
    result.w = s*v.w;
    return result;
}

*/
REAL
intersect( const Vector4& eyePos,
           const QVector<SceneObject>& objects,
           const Vector4& d,
           int& objectIndex,
           int& faceIndex,
           KdTree* tree,
           AABB extends,
           bool refract
           )
{
        REAL minT = POS_INF;
        REAL resultT = -1;
        int tempFaceIndex = -1;
        if( settings.useKdTree && tree && !refract )
        {
            assert( EQ( eyePos.w, 1) && EQ(d.w, 0) );

            REAL near, far;
            doIntersectRayKdBox( eyePos, d, near, far, extends );
            if( near <= 0&&far <= 0 )
                return -1;

            QVector<KdTreeNode*> nodeStack;
            KdTreeNode* current = tree->getRoot();
            while( current )
            {
                while( !current->isLeaf() )
                {
                    AABB curBox = current->getAABB();
                    REAL near, far;
                    doIntersectRayKdBox( eyePos, d, near, far, curBox );
                    int axis = current->getAxis();
                    float splitPos = current->getSplitPos();
                    if( near == far )  // inside the box
                        near = 0;
                    Vector4 nearPos = eyePos + d*near;
                    Vector4 farPos = eyePos + d*far;
                    if( nearPos.data[axis] <= splitPos  )
                    {
                        if( farPos.data[axis] <= splitPos )
                        {
                            current = current->getLeft();
                            continue;
                        }
                        KdTreeNode* right = current->getRight();
                        current = current->getLeft();

                        // Preserve the right
                        nodeStack.push_back( right );
                    }
                    else
                    {
                        if( farPos.data[axis] > splitPos )
                        {
                            current=current->getRight();
                            continue;
                        }
                        KdTreeNode* left = current->getLeft();
                        current = current->getRight();
                        nodeStack.push_back( left );
                    }
                }

                // Then we found an near leaf, find if there is intersect
                ObjectNode* objList = current->getObjectList();
                minT = POS_INF;
                while( objList )
                {
                    SceneObject* curObj =objList->getObject();
                    Matrix4x4 invCompMat = (*curObj).m_invTransform;

                    Vector4 eyePosObjSpace = invCompMat*eyePos;
                    Vector4 dObjSpace = invCompMat*d;

                    REAL t = doIntersect( *curObj, eyePosObjSpace, dObjSpace, tempFaceIndex);
                    if( t>0 && t < minT )
                    {
                        minT = t;
                        objectIndex = curObj->m_arrayID;
                        faceIndex = tempFaceIndex;
                    }
                    objList = objList->getNext();
                }
                Vector4 dst = (eyePos + minT*d);
                // Here we need to enlarge the bounding box a little bit
                AABB curBox = AABB( current->getAABB().getPos() - Vector3( EPSILON, EPSILON, EPSILON ),
                               current->getAABB().getSize() + 2*Vector3( EPSILON, EPSILON, EPSILON ));
                if( minT != POS_INF && curBox.contains(Vector3(dst.x, dst.y, dst.z ) ) )
                {
                    resultT = minT;
                    break;
                }
                // Else we need to get one node from the stack
                if( nodeStack.empty() )
                {
                    // No more nodes, meaning there is no intersect
                    break;
                }
                else
                {
                    current = nodeStack.at(nodeStack.size()-1);
                    nodeStack.pop_back();
                }
            }
            /**
                GPU code, preserve for future test
              **/
            /*
            float near, far;
            KdTreeNodeHost root = kdnode_test[0];
            cl_float4 eye4;
            eye4.x = eyePos.x;
            eye4.y = eyePos.y;
            eye4.z = eyePos.z;
            eye4.w = eyePos.w;
            cl_float4 d4;
            d4.x = d.x;
            d4.y = d.y;
            d4.z = d.z;
            d4.w = d.w;
            doIntersectRayKdBox2( eye4, d4, &near, &far, root.boxBegin, root.boxSize );
            if( near <= 0 && far <= 0 )
                return -1;
        //    else
         //      return 1;
            int nodeStack[1024];
            int stackTop = 0;
            int nextIndex = 0;

            while( nextIndex != -1 )
            {
                KdTreeNodeHost current = kdnode_test[nextIndex];

                while( !current.leaf )
                {
                    cl_float3 curBoxStart = current.boxBegin;
                    cl_float3 curBoxSize = current.boxSize;
                    float near, far;
                    doIntersectRayKdBox2( eye4, d4, &near, &far, curBoxStart, curBoxSize );
                    int axis = current.axis;
                    float splitPos = current.split;
                    if( near == far )  // inside the box
                        near = 0;
                    cl_float4 nearPos = add4(eye4, mult4(near, d4));
                    cl_float4 farPos = add4(eye4, mult4(far, d4));
                    if( getAxisElem4(nearPos, axis) <= splitPos  )
                    {
                        if( getAxisElem4(farPos, axis) <= splitPos )
                        {
                            //nextIndex = current.leftIndex;
                            current = kdnode_test[current.leftIndex];
                            continue;
                        }
                        nodeStack[stackTop++] = current.rightIndex;
                        current = kdnode_test[current.leftIndex];

                        // Preserve the right

                    }
                    else
                    {
                        if( getAxisElem4(farPos, axis) > splitPos )
                        {
                         //   nextIndex = current.rightIndex;
                            current = kdnode_test[current.rightIndex];
                            continue;
                        }
                        //KdTreeNodeHost left = kdnode_test[current.leftIndex];
                        nodeStack[stackTop++] = current.leftIndex;
                        current = kdnode_test[current.rightIndex];

                    }
                }

                // Then we found an near leaf, find if there is intersect
                int objIndex = current.objIndex;

                minT = POS_INF;

                while( objIndex != -1 )
                {
                    ObjectNodeHost objList = objnode_test[objIndex];
                    int sceneObjIndex = objList.objectIndex;

                    const SceneObject& curSceneObj = objects[sceneObjIndex];

                    Matrix4x4 invCompMat = curSceneObj.m_invTransform;

                    Vector4 eyePosObjSpace = invCompMat*eyePos;
                    Vector4 dObjSpace = invCompMat*d;

                    REAL t = doIntersect( curSceneObj, eyePosObjSpace, dObjSpace, tempFaceIndex);

                    if( t>0 && t < minT )
                    {
                        minT = t;
                        objectIndex = sceneObjIndex;
                        faceIndex = tempFaceIndex;
                    }
                    objIndex = objList.nextNodeIndex;
                  }


                //cl_float4 dst = add4(eye4,  mult4(minT, d4));
                Vector4 dst = eyePos + minT*d;
                // Here we need to enlarge the bounding box a little bit
                cl_float3 ep1;
                ep1.x = -EPSILON; ep1.y = -EPSILON; ep1.z = -EPSILON;
                cl_float3 ep2;
                ep2.x = 2*EPSILON; ep2.y = 2*EPSILON; ep2.z = 2*EPSILON;
                cl_float3 boxStart = add3(current.boxBegin , ep1);
                cl_float3 boxSize = add3(current.boxSize, ep2 );
                cl_float3 dst3;
                dst3.x = dst.x;
                dst3.y = dst.y;
                dst3.z = dst.z;

                if( minT != POS_INF && boxContain( boxStart, boxSize, dst3 ) )
                {
                    resultT = minT;
                    //resultT = 1;
                    break;
                }
                // Else we need to get one node from the stack
                if( stackTop == 0 )
                {
                    // No more nodes, meaning there is no intersect
                    int a = 0;
                    break;
                }
                else
                {
                    nextIndex = nodeStack[--stackTop];
                }
            }*/
        }
        else
        {
            for( int i = 0; i < objects.size(); i++ )
            {
                const SceneObject& curObj = objects[i];
                Matrix4x4 invCompMat = curObj.m_invTransform;

                Vector4 eyePosObjSpace = invCompMat*eyePos;
                Vector4 dObjSpace = invCompMat*d;

                REAL t = doIntersect( curObj, eyePosObjSpace, dObjSpace, tempFaceIndex);
                if( t>0 && t < minT )
                {
                    minT = t;
                    objectIndex = i;
                    faceIndex = tempFaceIndex;
                }
            }
            if( minT != POS_INF  )
            {
                resultT = minT;
            }
        }
        return resultT;
}
Ejemplo n.º 17
0
/**
//create Ellipse inscribed in a quadrilateral
*
*algorithm: http://chrisjones.id.au/Ellipses/ellipse.html
*finding the tangential points and ellipse center
*
*@Author Dongxu Li
*/
bool	RS_Ellipse::createInscribeQuadrilateral(const QVector<RS_Line*>& lines)
{
    if(lines.size() != 4) return false; //only do 4 lines

    QVector<RS_Line*> quad;
    for(int i=0;i<lines.size();i++){//copy the line pointers
        quad.push_back(lines[i]);
    }
    //    std::cout<<"0\n";
    for(int i=0;i<lines.size()*2;i++){//move parallel lines to opposite
        int j=(i+1)%lines.size();

        //        std::cout<<"("<<i<<","<<j<<")\n";
        //        std::cout<<*quad[i]<<std::endl;
        //        std::cout<<*quad[j]<<std::endl;
        RS_VectorSolutions sol=RS_Information::getIntersectionLineLine(quad[i%lines.size()],quad[j]);
        if(sol.getNumber()==0) {
            std::swap( quad[j],quad[ (i+2)%lines.size()]); //move to oppose
            i++;
        }
    }
    //    std::cout<<"========1========\n";

    QVector<RS_Line> ip;
    for(int i=1;i<4;i++){//find intersections
        //(0,i)
        //        std::cout<<"(0,"<<i<<")\n";
        RS_VectorSolutions sol0=RS_Information::getIntersectionLineLine(quad[0],quad[i]);
        if(sol0.getNumber()==0) continue;
        int l(1);
        if( l==i) l++;
        int m(l+1);
        if( m==i) m++;
        // lines in two pairs: (0, i) and (l,m)
        //        std::cout<<"(0,"<<i<<"):("<<l<<","<<m<<")\n";
        RS_VectorSolutions sol1=RS_Information::getIntersectionLineLine(quad[l],quad[m]);
        if(sol1.getNumber()==0) continue;

        ip.push_back(RS_Line(sol0.get(0),sol1.get(0)));
    }

    //    std::cout<<"20 ip.size()="<<ip.size()<<"\n";
    if(ip.size()<2) return false; //not enough connecting lines, so, no quadrilateral defined
    //    std::cout<<"22\n";
    RS_VectorSolutions sol2=RS_Information::getIntersection( & ip[0],& ip[1],true);
    if(ip.size() == 3) {//find intersecting pair
        //    RS_VectorSolutions sol0=RS_Information::getIntersection(line0,line1,true);
        RS_VectorSolutions sol1=RS_Information::getIntersection(&ip[2],&ip[1],true);
        if(sol1.getNumber()) {
            ip[0]=ip[2];
        }else{
            sol1=RS_Information::getIntersection(& ip[2],&ip[0],true);
            if(sol1.getNumber()) {
                ip[1]=ip[2];
            }
        }
    }
    RS_VectorSolutions sol=RS_Information::getIntersection( & ip[0],& ip[1],true);
    if(sol.getNumber()==0) {//this should not happen
//        RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Ellipse::createInscribeQuadrilateral(): can not locate projection Center");
        RS_DEBUG->print("RS_Ellipse::createInscribeQuadrilateral(): can not locate projection Center");
        return false;
    }
    RS_Vector centerProjection(sol.get(0));
//        std::cout<<"RS_Ellipse::createInscribe(): centerProjection="<<centerProjection<<std::endl;

    QVector<RS_Line> edge; //form the closed quadrilateral with ordered edges
    edge.push_back(RS_Line(ip[0].getStartpoint(),ip[1].getStartpoint()));
    edge.push_back(RS_Line(ip[1].getStartpoint(),ip[0].getEndpoint()));
    edge.push_back(RS_Line(ip[0].getEndpoint(),ip[1].getEndpoint()));
    edge.push_back(RS_Line(ip[1].getEndpoint(),ip[0].getStartpoint()));
    QVector<RS_Vector> tangent;//holds the tangential points on edges, in the order of edges: 1 3 2 0
    for(int i=0;i<=1;i++) {
        RS_VectorSolutions sol1=RS_Information::getIntersection(& edge[i],& edge[(i+2)%edge.size()],false);
        RS_Vector direction;
        if(sol1.getNumber()==0) {
            direction=edge[i].getEndpoint()-edge[i].getStartpoint();
        }else{
            direction=sol1.get(0)-centerProjection;
        }
        //                std::cout<<"Direction: "<<direction<<std::endl;
        RS_Line l(centerProjection, centerProjection+direction);
        for(int k=1;k<=3;k+=2){
            RS_VectorSolutions sol2=RS_Information::getIntersection(&l, &edge[(i+k)%edge.size()],false);
            for(int j=0;j<sol2.getNumber();j++) {
                tangent.push_back(sol2.get(j));
                //                std::cout<<"Tangential: "<<tangent.size()<<": "<<sol2.get(j)<<std::endl;
            }
        }
    }

    RS_Line* cl0=new RS_Line(ip[0].getEndpoint(),(tangent[0]+tangent[2])*0.5);
    RS_Line* cl1=new RS_Line(ip[1].getEndpoint(),(tangent[1]+tangent[2])*0.5);
    sol=RS_Information::getIntersection(cl0,cl1,false);
    if(sol.getNumber()==0){
        //this should not happen
//        RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Ellipse::createInscribeQuadrilateral(): can not locate Ellipse Center");
        RS_DEBUG->print("RS_Ellipse::createInscribeQuadrilateral(): can not locate Ellipse Center");
        return false;
    }
    RS_Vector center(sol.get(0));
//                    std::cout<<"line0: "<<*cl0<<std::endl;
//                    std::cout<<"line1: "<<*cl1<<std::endl;
//                    std::cout<<"center: "<<center<<std::endl;
    delete cl0;
    delete cl1;

//    double ratio;
    //        std::cout<<"dn="<<dn[0]<<' '<<dn[1]<<' '<<dn[2]<<std::endl;
    QVector<double> dn(3);
    RS_Vector angleVector(false);

    for(int i=0;i<tangent.size();i++) {
        tangent[i] -= center;//relative to ellipse center
    }
    QVector<QVector<double> > mt;
    mt.clear();
    for(int i=0;i<tangent.size();i++){//form the linear equation
        RS_Vector vp(tangent[i]);
//        std::cout<<"point "<<i<<" : "<<vp<<std::endl;
        QVector<double> mtRow;
        mtRow.push_back(vp.x*vp.x);
        mtRow.push_back(vp.x*vp.y);
        mtRow.push_back(vp.y*vp.y);
        bool addRow(true);
        for(int j=0;j<mt.size();j++){
            if(  fabs(mtRow[0]-mt[j][0])<RS_TOLERANCE &&
                 fabs(mtRow[1]-mt[j][1])<RS_TOLERANCE &&
                 fabs(mtRow[2]-mt[j][2])<RS_TOLERANCE){
                //symmetric
                addRow=false;
                break;
            }
        }
        if(addRow) {
            mtRow.push_back(1.);
            mt.push_back(mtRow);
        }
    }
//    std::cout<<"mt.size()="<<mt.size()<<std::endl;
    switch(mt.size()){
    case 2:{// the quadrilateral is a parallelogram
        //fixme, need to handle degenerate case better
        //        double angle(center.angleTo(tangent[0]));
        RS_Vector majorP(tangent[0]);
        double dx(majorP.magnitude());
        if(dx<RS_TOLERANCE*RS_TOLERANCE) return false; //refuse to return zero size ellipse
        angleVector.set(majorP.x/dx,-majorP.y/dx);
        for(int i=0;i<tangent.size();i++)tangent[i].rotate(angleVector);

        RS_Vector minorP(tangent[2]);
        double dy2(minorP.squared());
        if(fabs(minorP.y)<RS_TOLERANCE || dy2<RS_TOLERANCE*RS_TOLERANCE) return false; //refuse to return zero size ellipse
        // y'= y
        // x'= x-y/tan
        // reverse scale
        // y=y'
        // x=x'+y' tan
        //
        double ia2=1./(dx*dx);
        double ib2=1./(minorP.y*minorP.y);
        //ellipse scaled:drawi
        // ia2*x'^2+ib2*y'^2=1
        // ia2*(x-y*minor.x/minor.y)^2+ib2*y^2=1
        // ia2*x^2 -2*ia2*minor.x/minor.y xy + ia2*minor.x^2*ib2 y^2 + ib2*y^2 =1
        dn[0]=ia2;
        dn[1]=-2.*ia2*minorP.x/minorP.y;
        dn[2]=ib2*ia2*minorP.x*minorP.x+ib2;
    }
        break;
    case 4:
        mt.pop_back(); //only 3 points needed to form the qudratic form
        if ( ! RS_Math::linearSolver(mt,dn) ) return false;
        break;
    default:
        RS_DEBUG->print(RS_Debug::D_WARNING,"No inscribed ellipse for non isosceles trapezoid");
        return false; //invalid quadrilateral
    }

    setCenter(center);
    if(! createFromQuadratic(dn)) return false;

    if(angleVector.valid) {//need to rotate back, for the parallelogram case
        angleVector.y *= -1.;
        rotate(center,angleVector);
    }
    return true;

}
void InputWindow::on_button_ProcessData_released()
{
    //test if there is valid data in both fields and then process a schedule
    //PROCESS LEARN FILE
    if (ui->lineEdit_csvPathForItems->text().size() == 0) {
        QMessageBox invalid;
        invalid.setText("Be sure to pick an LearnFile (above)");
        invalid.setWindowTitle("Cannot Continue");
        invalid.exec();
    } else if (ui->lineEdit_csvPathForSchedule->text().size() == 0) {
        QMessageBox invalid;
        invalid.setText("Be sure to pick an Schedule File (above)");
        invalid.setWindowTitle("Cannot Continue");
        invalid.exec();
    } else {
        FullCalendar.clear();
        QString filename = (ui->lineEdit_csvPathForItems->text());
//        qDebug() << "Your item file is " << filename;
        QFile learnfile(filename);
        if (!learnfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
            qDebug() << learnfile.errorString();
        }
        QString AllLearnData = learnfile.readAll();
        //     qDebug() << AllLearnData;
        if (learnfile.isOpen()) learnfile.close();
        //makes a vector list of all the data in the learnfile provided
        while (!AllLearnData.isEmpty()) {
            QString tmpname;
            int index = AllLearnData.indexOf(',');
            //   qDebug() << index;
            tmpname.resize(index);
            for (int i = 0; i < index; i++) { tmpname[i] = AllLearnData[i]; }
            //     qDebug() << tmpname;
            AllLearnData.replace(0, index+1, "");
            //      qDebug() << AllLearnData;
            index = AllLearnData.indexOf('\n');
            //      qDebug() << index;
            QString tmp;
            for (int i = 0; i < index; i++) { tmp[i] = AllLearnData[i]; }
            int tmppriority = tmp.toInt();
            AllLearnData.replace(0, index+1, "");
            //        qDebug() << tmppriority;
            //       qDebug() << AllLearnData;
            LearnItem * newitem = new LearnItem;
            newitem->setName(tmpname);
            newitem->setPriority(tmppriority);
            learnlist.push_back(*newitem);
            delete newitem;
        }
        //sort all the items by priority  //BUBBLESORT
        int workingsize = learnlist.size();
        bool swaphappened = false;
//        qDebug() << "Sorting...";
        do {
            swaphappened = false;
            for (int i = 1; i < workingsize; i++) {
                if (learnlist[i-1].getPriority() < learnlist[i].getPriority()) {
                    LearnItem tmp;
                    tmp.setName(learnlist[i-1].getName());
                    tmp.setPriority(learnlist[i-1].getPriority());
                    learnlist[i-1].setName(learnlist[i].getName());
                    learnlist[i-1].setPriority(learnlist[i].getPriority());
                    learnlist[i].setName(tmp.getName());
                    learnlist[i].setPriority(tmp.getPriority());
                    //  qDebug() << "Swap! " << i;
                    swaphappened = true;
                }
            }
        } while (swaphappened);
//        qDebug() << "Sorting Complete";
//        for (int i = 0; i < learnlist.size(); i++) {
//            qDebug() << learnlist[i].getPriority() << " | " << learnlist[i].getName();
//        }
        //PROCESS SCHEDULE FILE
        QString filename2 = (ui->lineEdit_csvPathForSchedule->text());
//        qDebug() << "Your availablity file is " << filename2;
        QFile calfile(filename2);
        if (!calfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
            qDebug() << calfile.errorString();
        }
        QString AllCalData = calfile.readAll();
        //    qDebug() << AllCalData;
        if (calfile.isOpen()) calfile.close();

        int freedays = AllCalData.count("FREE");     //Find the number of free days
//        qDebug() << "Free Days: " << freedays;
//        qDebug() << "Size of LearnFile: " << learnlist.size();
        while (learnlist.size() > freedays) {   //If there are less free days than there are learnitems, cut some least important learn items
            learnlist.pop_back();
        }
//        qDebug() << "Size of LearnFile after sizing to Free Days: " << learnlist.size();
//        qDebug() << "Randomizing LearnItems onto your available time slots.";
        for (int i = 0; i < learnlist.size(); i++) {
            int randomarea = rand() % freedays + 1;
            //      qDebug() << "Random Area: " << randomarea;
            int currentpos = 0;
            for (int j = 0; j < randomarea; j++) {
                if (currentpos == 0) currentpos = AllCalData.indexOf("FREE");
                else currentpos = AllCalData.indexOf("FREE", currentpos+4);
            }
            AllCalData.replace(currentpos, 4, learnlist[i].getName());
            freedays--;
        }
        // qDebug() << AllCalData;

        do {
            if (freedays > 0) {
                int tmp = (learnlist.size() / 2);  //take the remaining and assign the top half again to any free space
                for (int i = 0; i < tmp; i++) {
                    learnlist.pop_back();
                }
//                qDebug() << "  ->>Top half of learn list:";
//                for (int i = 0; i < learnlist.size(); i++) {
//                    qDebug() << learnlist[i].getPriority() << " | " << learnlist[i].getName();
//                }
                if (learnlist.size() > freedays) {  //If there are less free days than there are learnitems, cut some least important learn items
                    for (int i = 0; i < freedays; i++) {
                        learnlist.pop_back();
                    }
                }
                for (int i = 0; i < learnlist.size(); i++) {
                    int randomarea = rand() % freedays + 1;
                    //    qDebug() << "Random Area: " << randomarea;
                    int currentpos = 0;
                    for (int j = 0; j < randomarea; j++) {
                        if (currentpos == 0) currentpos = AllCalData.indexOf("FREE");
                        else currentpos = AllCalData.indexOf("FREE", currentpos+4);
                    }
                    AllCalData.replace(currentpos, 4, learnlist[i].getName());
                    freedays--;
                }
            }
            //  qDebug() << AllCalData;
        } while (freedays > 0);   //repeat till none left
        //we will now have a filled out availability map
        FullCalendar = AllCalData;
//        ui->textBrowser_InfoAboutSchedule->setText(FullCalendar);   /item removed
        if(FullCalendar.size() > 10) {
            QMessageBox success;
            success.setText("Okay looks like the file processed just fine.");
            success.setWindowTitle("Good To Go");
            success.exec();
            learnlist.clear();
        }
    }
//    qDebug() << "Completed making the schedule.";
}
Ejemplo n.º 19
0
void TabDiveStatistics::updateData()
{
	clear();
	ui->depthLimits->setMaximum(get_depth_string(stats_selection.max_depth, true));
	if (amount_selected > 1)
		ui->depthLimits->setMinimum(get_depth_string(stats_selection.min_depth, true));
	else
		ui->depthLimits->setMinimum("");
	// the overall average depth is really confusing when listed between the
	// deepest and shallowest dive - let's just not set it
	// ui->depthLimits->setAverage(get_depth_string(stats_selection.avg_depth, true));

	// Also hide the avgIco, so its clear that its not there.
	ui->depthLimits->overrideAvgToolTipText("");
	ui->depthLimits->setAvgVisibility(false);

	if (stats_selection.max_sac.mliter && (stats_selection.max_sac.mliter != stats_selection.avg_sac.mliter))
		ui->sacLimits->setMaximum(get_volume_string(stats_selection.max_sac, true).append(tr("/min")));
	else
		ui->sacLimits->setMaximum("");
	if (stats_selection.min_sac.mliter && (stats_selection.min_sac.mliter != stats_selection.avg_sac.mliter))
		ui->sacLimits->setMinimum(get_volume_string(stats_selection.min_sac, true).append(tr("/min")));
	else
		ui->sacLimits->setMinimum("");
	if (stats_selection.avg_sac.mliter)
		ui->sacLimits->setAverage(get_volume_string(stats_selection.avg_sac, true).append(tr("/min")));
	else
		ui->sacLimits->setAverage("");

	temperature_t temp;
	temp.mkelvin = stats_selection.max_temp;
	ui->tempLimits->setMaximum(get_temperature_string(temp, true));
	temp.mkelvin = stats_selection.min_temp;
	ui->tempLimits->setMinimum(get_temperature_string(temp, true));
	if (stats_selection.combined_temp && stats_selection.combined_count) {
		const char *unit;
		get_temp_units(0, &unit);
		ui->tempLimits->setAverage(QString("%1%2").arg(stats_selection.combined_temp / stats_selection.combined_count, 0, 'f', 1).arg(unit));
	}


	ui->divesAllText->setText(QString::number(stats_selection.selection_size));
	ui->totalTimeAllText->setText(get_dive_duration_string(stats_selection.total_time.seconds, tr("h"), tr("min"), tr("sec"),
		" ", displayed_dive.dc.divemode == FREEDIVE));
	
	int seconds = stats_selection.total_time.seconds;
	if (stats_selection.selection_size)
		seconds /= stats_selection.selection_size;
	ui->timeLimits->setAverage(get_dive_duration_string(seconds, tr("h"), tr("min"), tr("sec"),
			" ", displayed_dive.dc.divemode == FREEDIVE));
	if (amount_selected > 1) {
		ui->timeLimits->setMaximum(get_dive_duration_string(stats_selection.longest_time.seconds, tr("h"), tr("min"), tr("sec"),
			" ", displayed_dive.dc.divemode == FREEDIVE));
		ui->timeLimits->setMinimum(get_dive_duration_string(stats_selection.shortest_time.seconds, tr("h"), tr("min"), tr("sec"),
			" ", displayed_dive.dc.divemode == FREEDIVE));
	} else {
		ui->timeLimits->setMaximum("");
		ui->timeLimits->setMinimum("");
	}

	QVector<QPair<QString, int> > gasUsed;
	QString gasUsedString;
	volume_t vol;
	selectedDivesGasUsed(gasUsed);
	for (int j = 0; j < 20; j++) {
		if (gasUsed.isEmpty())
			break;
		QPair<QString, int> gasPair = gasUsed.last();
		gasUsed.pop_back();
		vol.mliter = gasPair.second;
		gasUsedString.append(gasPair.first).append(": ").append(get_volume_string(vol, true)).append("\n");
	}
	if (!gasUsed.isEmpty())
		gasUsedString.append("...");
	volume_t o2_tot = {}, he_tot = {};
	selected_dives_gas_parts(&o2_tot, &he_tot);

	/* No need to show the gas mixing information if diving
		* with pure air, and only display the he / O2 part when
		* it is used.
		*/
	if (he_tot.mliter || o2_tot.mliter) {
		gasUsedString.append(tr("These gases could be\nmixed from Air and using:\n"));
		if (he_tot.mliter) {
			gasUsedString.append(tr("He"));
			gasUsedString.append(QString(": %1").arg(get_volume_string(he_tot, true)));
		}
		if (he_tot.mliter && o2_tot.mliter)
			gasUsedString.append(" ").append(tr("and")).append(" ");
		if (o2_tot.mliter) {
			gasUsedString.append(tr("O₂"));
			gasUsedString.append(QString(": %2\n").arg(get_volume_string(o2_tot, true)));
		}
	}
	ui->gasConsumption->setText(gasUsedString);
}