Пример #1
0
void MainWindow::trainingDataChanged()
{
    QList<QImage> maleTrainingImages = ui->lblMaleTraining->getImages();
    QVector<int> maleLabels;
    maleLabels.fill(MALEINDEX,maleTrainingImages.count());

    QList<QImage> femaleTrainingImages = ui->lblFemaleTraining->getImages();
    QVector<int> femaleLabels;
    femaleLabels.fill(FEMALEINDEX,femaleTrainingImages.count());

    if (maleTrainingImages.isEmpty()) {
        ui->listWidget->addItem(QString("%1: %2").arg(QTime::currentTime().toString("hh:mm"), "Need male images..."));
    }
    if (femaleTrainingImages.isEmpty()) {
        ui->listWidget->addItem(QString("%1: %2").arg(QTime::currentTime().toString("hh:mm"), "Need female images..."));
    }
    if (maleTrainingImages.isEmpty()||femaleTrainingImages.isEmpty())
        return;
    //
    QList<QImage> trainingImages;
    QVector<int> labels;
    trainingImages << maleTrainingImages << femaleTrainingImages;
    labels << maleLabels << femaleLabels;
    //
    ui->listWidget->addItem(QString("%1: %2").arg(QTime::currentTime().toString("hh:mm"), "Training..."));
    recognizer->trainFaces(trainingImages, labels);
    ui->listWidget->addItem(QString("%1: %2").arg(QTime::currentTime().toString("hh:mm"), "Training complete."));
    reevaluateMale();
    reevaluateFemale();
}
Пример #2
0
lk_conv::lk_conv(int w, int h)
{
    QVector < QVector < float > > newkernel;
    QVector < float > nullrow;
    nullrow.fill (0,h);
    newkernel.fill (nullrow,w);
    kernel = newkernel;
    __width = w;
    __height = h;
}
Пример #3
0
void LcmsColorProfileContainer::DelinearizeFloatValueFast(QVector <double> & Value) const
{
    //we can only reliably delinearise in the 0-1.0 range, outside of that leave the value alone.
    QVector <quint16> TRCtriplet(3);
    TRCtriplet[0] = Value[0]*65535;
    TRCtriplet[1] = Value[1]*65535;
    TRCtriplet[2] = Value[2]*65535;
    

    if (d->hasColorants) {
        if (!cmsIsToneCurveLinear(d->redTRC) && Value[0]<1.0) {
            TRCtriplet[0] = cmsEvalToneCurve16(d->redTRCReverse, TRCtriplet[0]);
            Value[0] = TRCtriplet[0]/65535.0;
        }
        if (!cmsIsToneCurveLinear(d->greenTRC) && Value[1]<1.0) {
            TRCtriplet[1] = cmsEvalToneCurve16(d->greenTRCReverse, TRCtriplet[1]);
            Value[1] = TRCtriplet[1]/65535.0;
        }
        if (!cmsIsToneCurveLinear(d->blueTRC) && Value[2]<1.0) {
            TRCtriplet[2] = cmsEvalToneCurve16(d->blueTRCReverse, TRCtriplet[2]);
            Value[2] = TRCtriplet[2]/65535.0;
        }
            
    } else {
        if (cmsIsTag(d->profile, cmsSigGrayTRCTag) && Value[0]<1.0) {
            TRCtriplet[0] = (cmsEvalToneCurve16(d->grayTRCReverse, Value[0]*65535));
            Value.fill(TRCtriplet[0]/65535.0);
        }
    }
}
Пример #4
0
void KoskoStudy::fitToSize(QVector<int> &intPath
						   , const QVector<bool> &isInc
						   , QVector<int> &newImg
						   , const int &leftCM
						   , const int &rightCM
						   , const int &upperCM
						   , const int &bottomCM)
{
	int tmp, i;
	for (i = 0; i < intPath.size(); i += 2) {
		tmp = mXCMPos + (intPath[i] - leftCM) * ((double) (mWidth - 2 * mXCMPos)) / (rightCM - leftCM);
		intPath[i] = tmp;
		tmp = mYCMPos + (intPath[i + 1] - bottomCM) * ((double) (mHeight - 2 * mYCMPos)) / (upperCM - bottomCM);
		intPath[i + 1] = tmp;
	}
	newImg.clear();
	newImg.fill(0, mWidth * mHeight);
	for (i = 0; i < intPath.size() - 2; i += 2) {
		if (isInc[1 + i / 2]) {
			makeLine(intPath.at(i)
				 , intPath.at(i + 1)
				 , intPath.at(i + 2)
				 , intPath.at(i + 3)
				 , mWidth
				 , mHeight
				 , newImg);
		}
	}
}
Пример #5
0
bool BassPlayer::calcSpectrum(QList<QVector<float> > & result) {
    float fft[1024 * channels_count];
    BASS_ChannelGetData(chan, fft, BASS_DATA_FFT2048 | BASS_DATA_FFT_INDIVIDUAL | BASS_DATA_FFT_REMOVEDC);

    QVector<float> peaks;
    int b0 = 0, x, z, peakNum;

    for (x = 0; x < channels_count; x++)
        result.append(QVector<float>());

    for (x = 0; x < calcSpectrumBandsGroupCount(); x++) {
        peaks.fill(0, channels_count);

        int b1 = spectrumComplexPoints[x];

        for (; b0 < b1; b0++) {
            peakNum = b0 % channels_count;
            if (peaks[peakNum] < fft[b0])
                peaks[peakNum] = fft[b0];
        }

        for (z = 0; z < channels_count; z++)
            result[z].append(sqrt(peaks[z]));
    }

    return true;
}
Пример #6
0
void AdaptiveLayout::tKey::ArrangeProperties(const QHash<QString, int> &propsOrder, int max)
{
    QVector<int> permutation;
    permutation.resize(m_Properties.size());
    for( QHash<QString, int>::iterator i = m_Properties.begin(); i != m_Properties.end(); ++i )
    {
        int indexFrom = i.value();
        int indexTo = indexFrom;
        QHash<QString, int>::const_iterator p = propsOrder.find(i.key());
        if( p != propsOrder.end() )  // If we fail to find, the result may be incorrect
        {
            indexTo = p.value();
        }
        i.value() = indexTo;
        permutation[indexFrom] = indexTo;
    }
    QVector<float> newProps;
    newProps.resize(max + 1);
    for( int iactor = 0; iactor < m_Actors.size(); iactor++ )
    {
        tActor& actor = m_Actors[iactor];
        newProps.fill(0.f);
        for( int i = 0; i < actor.props.size(); i++ )
        {
            newProps[permutation[i]] = actor.props[i];
        }
        actor.props = newProps;
    }
}
QVector<quint8> EncryptorPrivate::mergeSort(const QVector<quint8> &array, quint32 salt, quint64 k)
{
    int length = array.size();

    if (length <= 1) {
        return array;
    }

    int middle = length / 2;
    QVector<quint8> left = array.mid(0, middle);
    QVector<quint8> right = array.mid(middle);

    left = mergeSort(left, salt, k);
    right = mergeSort(right, salt, k);

    int leftptr = 0;
    int rightptr = 0;

    QVector<quint8> sorted;
    sorted.fill(0, length);
    for (int i = 0; i < length; ++i) {
        if (rightptr == right.size() || (leftptr < left.size() && randomCompare(left[leftptr], right[rightptr], salt, k) <= 0)) {
            sorted[i] = left[leftptr++];
        } else if (leftptr == left.size() || (rightptr < right.size() && randomCompare(right[rightptr], left[leftptr], salt, k) <= 0)) {
            sorted[i] = right[rightptr++];
        }
    }
    return sorted;
}
Пример #8
0
void PieDiagram::shuffleLabels( QRectF* textBoundingRect )
{
    // things that could be improved here:
    // - use a variable number (chosen using angle information) of neighbors to check
    // - try harder to arrange the labels to look nice

    // ideas:
    // - leave labels that don't collide alone (only if they their offset is zero)
    // - use a graphics view for collision detection

    LabelPaintCache& lpc = d->labelPaintCache;
    const int n = lpc.paintReplay.size();
    bool modified = false;
    qreal direction = 5.0;
    QVector< qreal > offsets;
    offsets.fill( 0.0, n );

    for ( bool lastRoundModified = true; lastRoundModified; ) {
        lastRoundModified = false;

        for ( int i = 0; i < n; i++ ) {
            const int neighborsToCheck = qMax( 10, lpc.paintReplay.size() - 1 );
            const int minComp = wraparound( i - neighborsToCheck / 2, n );
            const int maxComp = wraparound( i + ( neighborsToCheck + 1 ) / 2, n );

            QPainterPath& path = lpc.paintReplay[ i ].labelArea;

            for ( int j = minComp; j != maxComp; j = wraparound( j + 1, n ) ) {
                if ( i == j ) {
                    continue;
                }
                QPainterPath& otherPath = lpc.paintReplay[ j ].labelArea;

                while ( ( offsets[ i ] + direction > 0 ) && otherPath.intersects( path ) ) {
#ifdef SHUFFLE_DEBUG
                    qDebug() << "collision involving" << j << "and" << i << " -- n =" << n;
                    TextAttributes ta = lpc.paintReplay[ i ].attrs.textAttributes();
                    ta.setPen( QPen( Qt::white ) );
                    lpc.paintReplay[ i ].attrs.setTextAttributes( ta );
#endif
                    uint slice = lpc.paintReplay[ i ].index.column();
                    qreal angle = DEGTORAD( d->startAngles[ slice ] + d->angleLens[ slice ] / 2.0 );
                    qreal dx = cos( angle ) * direction;
                    qreal dy = -sin( angle ) * direction;
                    offsets[ i ] += direction;
                    path.translate( dx, dy );
                    lastRoundModified = true;
                }
            }
        }
        direction *= -1.07; // this can "overshoot", but avoids getting trapped in local minimums
        modified = modified || lastRoundModified;
    }

    if ( modified ) {
        for ( int i = 0; i < lpc.paintReplay.size(); i++ ) {
            *textBoundingRect |= lpc.paintReplay[ i ].labelArea.boundingRect();
        }
    }
}
void QmlProfilerRangeModel::computeNestingContracted()
{
    int i;
    int eventCount = count();

    int nestingLevels = QmlDebug::Constants::QML_MIN_LEVEL;
    int collapsedRowCount = nestingLevels + 1;
    QVector<qint64> nestingEndTimes;
    nestingEndTimes.fill(0, nestingLevels + 1);

    for (i = 0; i < eventCount; i++) {
        qint64 st = startTime(i);

        // per type
        if (nestingEndTimes[nestingLevels] > st) {
            if (++nestingLevels == nestingEndTimes.size())
                nestingEndTimes << 0;
            if (nestingLevels == collapsedRowCount)
                ++collapsedRowCount;
        } else {
            while (nestingLevels > QmlDebug::Constants::QML_MIN_LEVEL &&
                   nestingEndTimes[nestingLevels-1] <= st)
                nestingLevels--;
        }
        nestingEndTimes[nestingLevels] = st + duration(i);

        m_data[i].displayRowCollapsed = nestingLevels;
    }
    setCollapsedRowCount(collapsedRowCount);
}
Пример #10
0
bool CMapDEM::getOrigRegion(QVector<qint16>& data,projXY &topLeft, projXY &bottomRight, int& w, int& h)
{
    //memset(data, 0, sizeof(qint16) * h * w);
    data.fill(0);
    if(pjsrc == 0) return false;

    // 1. convert top left and bottom right point into the projection system used by the DEM data
    pj_transform(pjtar, pjsrc, 1, 0, &topLeft.u, &topLeft.v, 0);
    pj_transform(pjtar, pjsrc, 1, 0, &bottomRight.u, &bottomRight.v, 0);

    // 2. get floating point offset of topleft corner
    double xoff1_f = (topLeft.u - xref1) / xscale;
    double yoff1_f = (topLeft.v - yref1) / yscale;

    // 3. truncate floating point offset into integer offset
    int xoff1 = floor(xoff1_f);  //qDebug() << "xoff1:" << xoff1 << xoff1_f;
    int yoff1 = floor(yoff1_f);  //qDebug() << "yoff1:" << yoff1 << yoff1_f;

    // 4. get floating point offset of bottom right corner
    double xoff2_f = (bottomRight.u - xref1) / xscale;
    double yoff2_f = (bottomRight.v - yref1) / yscale;

    // 5. truncate floating point offset into integer offset.
    int xoff2 = ceil(xoff2_f);   //qDebug() << "xoff2:" << xoff2 << xoff2_f;
    int yoff2 = ceil(yoff2_f);   //qDebug() << "yoff2:" << yoff2 << yoff2_f;

    // 6. get width and height to read from file
    qint32 w1 = xoff2 - xoff1 + 1;
                                 //qDebug() << "w1:" << w1 << "h1:" << h1;
    qint32 h1 = yoff2 - yoff1 + 1;

    topLeft.u = xoff1 * xscale + xref1;
    topLeft.v = yoff1 * yscale + yref1;
    bottomRight.u = xoff2 * xscale + xref1;
    bottomRight.v = yoff2 * yscale + yref1;
    pj_transform(pjsrc, pjtar, 1, 0, &topLeft.u, &topLeft.v, 0);
    pj_transform(pjsrc, pjtar, 1, 0, &bottomRight.u, &bottomRight.v, 0);

    // memory sanity check
    if(double(w1) * double(h1) > pow(2.0f,31)) return false;

    if (w1 < w)
    {
        w = w1;
    }
    if (h1 < h)
    {
        h = h1;
    }

    Q_ASSERT(w1 <= w);
    Q_ASSERT(h1 <= h);

    // 7. read DEM data from file
    CPLErr err = dataset->RasterIO(GF_Read, xoff1, yoff1, w1, h1, data.data(), w, h, GDT_Int16, 1, 0, 0, 0, 0);
    return (err != CE_Failure);
}
Пример #11
0
void DLXSolver::printDLX (bool forced)
{
#ifdef DLX_LOG
    bool verbose = (forced || (mGraph->order() <= 5));

    if ((mEndNodeNum < 0) || (mEndColNum < 0)) {
        fprintf (stderr, "\nDLXSolver::printDLX(): EMPTY, mEndNodeNum %d, "
                "mEndRowNum %d, mEndColNum %d\n\n",
                mEndNodeNum, mEndRowNum, mEndColNum);
        return;
    }
    // fprintf (stderr, "\nDLX Matrix has %d cols, %d rows and %d ones\n\n",
                // mEndColNum + 1, mEndRowNum + 1, mEndNodeNum + 1);
    DLXNode * colDLX = mCorner->right;
    if (colDLX == mCorner) {
        fprintf (stderr, "DLXSolver::printDLX(): ALL COLUMNS ARE HIDDEN\n");
        return;
    }
    int totGap  = 0;
    int nRows   = 0;
    int nNodes  = 0;
    int lastCol = -1;
    QVector<DLXNode *> rowsRemaining;
    rowsRemaining.fill (0, mRows.count());
    if (verbose) fprintf (stderr, "\n");
    while (colDLX != mCorner) {
        int col = mColumns.indexOf(colDLX);
        if (verbose) fprintf (stderr, "Col %02d, %02d rows  ",
                              col, mColumns.at(col)->value);
        DLXNode * node = mColumns.at(col)->below;
        while (node != colDLX) {
            int rowNum = node->value;
            if (verbose) fprintf (stderr, "%02d ", rowNum);
            if (rowsRemaining.at (rowNum) == 0) {
                nRows++;
            }
            rowsRemaining[rowNum] = mRows.at (rowNum);
            nNodes++;
            node = node->below;
        }
        int gap = col - (lastCol + 1);
        if (gap > 0) {
            if (verbose) fprintf (stderr, "covered %02d", gap);
            totGap = totGap + gap;
        }
        if (verbose) fprintf (stderr, "\n");
        colDLX = colDLX->right;
        lastCol = col;
    }
    if (verbose) fprintf (stderr, "\n");
    fprintf (stderr, "Matrix NOW has %d rows, %d columns and %d ones\n",
            nRows, lastCol + 1 - totGap, nNodes);
#else
    Q_UNUSED (forced);
#endif
}
Пример #12
0
QVector<bool> NewBuildingWizard::GetLayout()
{
    if (field("NewSpecial").toBool())
    {
        return ((SpecialWizardPage*)page(SPECIAL_PAGE))->GetLayout();
    }
    QVector<bool> layout;
    layout.fill(false, 9 * 9 * 21);
    layout[0] = true;
    return layout;
}
Пример #13
0
void MainWindow::sampleFormatChanged()
{
    for (int i = 0; i < curves.size(); i++) {
        curves[i].curve->detach();
        delete curves[i].curve;
        curves[i].data->clear();
        delete curves[i].data;
    }
    curves.clear();
    timeAxis.clear();

    QList<sampleValue> sampleList = kwp.getSample();
    int numSamples = settingsDialog->rate * settingsDialog->historySecs + 1;

    timeAxis.clear();
    for (int i = 0; i < numSamples; i++) {
        timeAxis.prepend(-i / static_cast<double>(settingsDialog->rate));
    }

    int numColors = sizeof(colorList) / sizeof(QString);

    for (int i = 0; i < sampleList.length(); i++) {
        QwtPlotCurve* curve = new QwtPlotCurve;
        QVector<double>* data = new QVector<double>();
        data->reserve(numSamples+1);
        data->fill(0, numSamples);

        QColor curveColor;
        curveColor.setNamedColor(colorList[i % numColors]);

        int blockNum = sampleList.at(i).refs.at(0).blockNum;
        int pos = sampleList.at(i).refs.at(0).pos;
        blockLabels_t label = kwp.getBlockLabel(blockNum);
        QString desc = label.desc[pos] + " " + label.subDesc[pos];

        curve->setRenderHint(QwtPlotItem::RenderAntialiased);
        curve->setPen(curveColor);
        curve->setTitle(desc);

        curve->setRawSamples(timeAxis.constData(), data->constData(), numSamples);
        curve->attach(ui->plot);

        // set legend checked
        QwtLegendItem *legendItem = qobject_cast<QwtLegendItem*>(ui->plot->legend()->find(curve));
        if (legendItem) {
            legendItem->setChecked(true);
        }

        curveAndData tmp;
        tmp.curve = curve;
        tmp.data = data;
        curves.append(tmp);
    }
}
Пример #14
0
static void addHeaderSequence(QVector<int> &p_sequence, int p_level, int p_baseLevel)
{
    Q_ASSERT(p_level >= 1 && p_level < p_sequence.size());
    if (p_level < p_baseLevel) {
        p_sequence.fill(0);
        return;
    }

    ++p_sequence[p_level];
    for (int i = p_level + 1; i < p_sequence.size(); ++i) {
        p_sequence[i] = 0;
    }
}
Пример #15
0
void WireCreator::cEndsNForks()
{
    QVector<int> tempPoints;
    tempPoints.fill(0,vertices.length());
    for(auto pair : edges){
        tempPoints[pair.first]++;
        tempPoints[pair.second]++;

    }
    for(int i=0; i<tempPoints.length();i++){
        if(tempPoints[i]==1)deadEnds.push_back(i);
        if(tempPoints[i]>2)forks.push_back(i);
    }
}
Пример #16
0
QVector<double> KolmogorovZurbenko::kz1d(int iterations)
{
    QVector<double> *tmp = new QVector<double>(y);
    QVector<double> *ans = new QVector<double>(y.size());
    ans->fill(0.0);
    for(int i = 0; i < iterations; i++){
        for(int yi = 0; yi < y.size(); yi++){
            ans->operator [](yi) = mavg1d(*tmp, yi, WINDOW);
        }
        ans->swap(*tmp);
    }

    return *ans;
}
Пример #17
0
// returns the audio level for each channel
QVector<qreal> getBufferLevels(const QAudioBuffer& buffer)
{
    QVector<qreal> values;

    if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian)
        return values;

    if (buffer.format().codec() != "audio/pcm")
        return values;

    int channelCount = buffer.format().channelCount();
    values.fill(0, channelCount);
    qreal peak_value = getPeakValue(buffer.format());
    if (qFuzzyCompare(peak_value, qreal(0)))
        return values;

    switch (buffer.format().sampleType()) {
    case QAudioFormat::Unknown:
    case QAudioFormat::UnSignedInt:
        if (buffer.format().sampleSize() == 32)
            values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount);
        if (buffer.format().sampleSize() == 16)
            values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount);
        if (buffer.format().sampleSize() == 8)
            values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount);
        for (int i = 0; i < values.size(); ++i)
            values[i] = qAbs(values.at(i) - peak_value / 2) / (peak_value / 2);
        break;
    case QAudioFormat::Float:
        if (buffer.format().sampleSize() == 32) {
            values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount);
            for (int i = 0; i < values.size(); ++i)
                values[i] /= peak_value;
        }
        break;
    case QAudioFormat::SignedInt:
        if (buffer.format().sampleSize() == 32)
            values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount);
        if (buffer.format().sampleSize() == 16)
            values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount);
        if (buffer.format().sampleSize() == 8)
            values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount);
        for (int i = 0; i < values.size(); ++i)
            values[i] /= peak_value;
        break;
    }

    return values;
}
Пример #18
0
void Field::throwBalls(int num, bool directly)
{
    QVector<QPoint> free;
    free.fill(QPoint(0, 0), W * H);
    int nFree = 0;
    for (int i = 0; i < W; i++)
        for (int j = 0; j < H; j++)
            if (at(i, j) == 0)
            {
                free[nFree] = QPoint(i, j);
                nFree++;
            }

#ifdef QT_DEBUG
    for (int i = 0; i < W * H; i++)
    {
        //qDebug("%d, %d", free[i].x(), free[i].y());
    }
#endif
    //return;

    QList<SuggestedBall> ballsToThrow;
    for (int n = 0; n < num; n++)
    {
        if (nFree > 0)
        {
            int at = qrand() % nFree;
            ballsToThrow.append({ free[at], qrand() % COLORS + 1, NULL, NULL });
            free.removeAt(at);
            nFree--;
        }
        else
            ballsToThrow.append({ QPoint(-1, -1), qrand() % COLORS + 1, NULL, NULL });
    }

    if (directly)
    {
        // This is needed on startup only, therefore do nothing except placing balls
        foreach (auto ball, ballsToThrow)
        {
            setAt(ball.pt, ball.color);
            QGraphicsObject *item = new SvgRendererItem(ResourceLoader::instance()->ball(ball.color));
            item->setPos(ball.pt * CELL_SIZE);
            item->setZValue(3);
            m_scene->addItem(item);
            setVectorAt(m_fieldItems, ball.pt, item);
        }
    }
Пример #19
0
QVector<float> ImageProcessor::findOccurrences(QImage input, int offset) {
    QVector<float> returnMe;
    returnMe.fill(0,256);
    float single = 1.0 / (input.width() * input.height());

    for(int x=0;x<input.width();x++) {
        for(int y=0;y<input.height();y++) {
            int pixelIndex = qRed(input.pixel(x,y)) + offset;
            pixelIndex = qMax(pixelIndex,0);
            pixelIndex = qMin(pixelIndex,255);
            float newVal = returnMe.value(pixelIndex)+single;
            returnMe.replace(pixelIndex,newVal);
        }
    }

    return returnMe;
}
Пример #20
0
void Analyzer::processSpectrum()
{
    m_spectrumHistory[m_currentSpectrum].swap(m_spectrum);
    m_currentSpectrum = (m_currentSpectrum + 1) % m_numSpectra;

    static QVector<qreal> average;
    average.fill(0, m_outputSize);

    for (const auto &h : m_spectrumHistory) {
        auto hPoint = h.constBegin();
        for (auto &a : average)
            a +=  hPoint++->amplitude;
    }

    auto n = m_noiseSpectrum.constBegin();
    auto a = average.constBegin();
    for (auto &s : m_spectrum) {
        s.amplitude = std::max(0.0,  *a / m_numSpectra - n->amplitude);
        ++n; ++a;
    }
}
Пример #21
0
// Build RMSD statistics from iteration models
void US_DmgaMcStats::build_rmsd_stats( int niters,
      QVector< US_Model >& imodels, QVector< double >& rstats )
{
   const int stsiz    = 23;
   QVector< double > rmsds;
   QVector< double > rconcs;

   rstats.fill( 0.0, stsiz );

   // Get statistics for RMSDs
   for ( int jj = 0; jj < niters; jj++ )
   {
      double rmsd      = sqrt( imodels[ jj ].variance );
      rmsds  << rmsd;
      rconcs << 1.0;
   }

   compute_statistics( niters, rmsds, rconcs, rstats );
qDebug() << "Dst:BRs:   iters" << niters << "RMSD min max mean median"
   << rstats[0] << rstats[1] << rstats[2] << rstats[3];
}
Пример #22
0
std::vector<std::vector<T> >
#else
QVector<QVector<T> >
#endif
KuhnMunkres::make_grid(int size, T value)
{
#ifdef USE_STL
    std::vector<std::vector<T> > grid;
    grid.resize(size, std::vector<T>());
#else
    QVector<QVector<T> > grid;
    grid.fill(QVector<T>(), size);
#endif
    for (int row = 0; row < size; ++row)
#ifdef USE_STL
        grid[row].resize(size, value);
#else
        grid[row].fill(value, size);
#endif
    return grid;
}
Пример #23
0
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
    // compute default joint transforms
    int numStates = _rig->getJointStateCount();
    QVector<glm::mat4> transforms;
    transforms.fill(glm::mat4(), numStates);

    // compute bounding box that encloses all shapes
    Extents totalExtents;
    totalExtents.reset();
    totalExtents.addPoint(glm::vec3(0.0f));
    for (int i = 0; i < numStates; i++) {
        // compute the default transform of this joint
        const JointState& state = _rig->getJointState(i);
        int parentIndex = state.getParentIndex();
        if (parentIndex == -1) {
            transforms[i] = _rig->getJointTransform(i);
        } else {
            glm::quat modifiedRotation = state.getPreRotation() * state.getDefaultRotation() * state.getPostRotation();
            transforms[i] = transforms[parentIndex] * glm::translate(state.getTranslation())
                * state.getPreTransform() * glm::mat4_cast(modifiedRotation) * state.getPostTransform();
        }

        // Each joint contributes a sphere at its position
        glm::vec3 axis(state.getBoneRadius());
        glm::vec3 jointPosition = extractTranslation(transforms[i]);
        totalExtents.addPoint(jointPosition + axis);
        totalExtents.addPoint(jointPosition - axis);
    }

    // compute bounding shape parameters
    // NOTE: we assume that the longest side of totalExtents is the yAxis...
    glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
    // ... and assume the radius is half the RMS of the X and Z sides:
    _boundingCapsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
    _boundingCapsuleHeight = diagonal.y - 2.0f * _boundingCapsuleRadius;

    glm::vec3 rootPosition = _rig->getJointState(geometry.rootJointIndex).getPosition();
    _boundingCapsuleLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
    _boundingRadius = 0.5f * glm::length(diagonal);
}
Пример #24
0
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
    // compute default joint transforms
    int numStates = _jointStates.size();
    assert(numStates == _shapes.size());
    QVector<glm::mat4> transforms;
    transforms.fill(glm::mat4(), numStates);

    // compute bounding box that encloses all shapes
    Extents totalExtents;
    totalExtents.reset();
    totalExtents.addPoint(glm::vec3(0.0f));
    for (int i = 0; i < numStates; i++) {
        // compute the default transform of this joint
        JointState& state = _jointStates[i];
        const FBXJoint& joint = state.getFBXJoint();
        int parentIndex = joint.parentIndex;
        if (parentIndex == -1) {
            transforms[i] = _jointStates[i].getTransform();
        } else {
            glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;    
            transforms[i] = transforms[parentIndex] * glm::translate(joint.translation) 
                * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
        }

        // Each joint contributes its point to the bounding box
        glm::vec3 jointPosition = extractTranslation(transforms[i]);
        totalExtents.addPoint(jointPosition);

        Shape* shape = _shapes[i];
        if (!shape) {
            continue;
        }

        // Each joint with a shape contributes to the totalExtents: a box 
        // that contains the sphere centered at the end of the joint with radius of the bone.

        // TODO: skip hand and arm shapes for bounding box calculation
        int type = shape->getType();
        if (type == CAPSULE_SHAPE) {
            // add the two furthest surface points of the capsule
            CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
            float radius = capsule->getRadius();
            glm::vec3 axis(radius);
            Extents shapeExtents;
            shapeExtents.reset();
            shapeExtents.addPoint(jointPosition + axis);
            shapeExtents.addPoint(jointPosition - axis);
            totalExtents.addExtents(shapeExtents);
        } else if (type == SPHERE_SHAPE) {
            float radius = shape->getBoundingRadius();
            glm::vec3 axis(radius);
            Extents shapeExtents;
            shapeExtents.reset();
            shapeExtents.addPoint(jointPosition + axis);
            shapeExtents.addPoint(jointPosition - axis);
            totalExtents.addExtents(shapeExtents);
        }
    }

    // compute bounding shape parameters
    // NOTE: we assume that the longest side of totalExtents is the yAxis...
    glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
    // ... and assume the radius is half the RMS of the X and Z sides:
    float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
    _boundingShape.setRadius(capsuleRadius);
    _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);

    glm::vec3 rootPosition = _jointStates[geometry.rootJointIndex].getPosition();
    _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
    _boundingRadius = 0.5f * glm::length(diagonal);
}
Пример #25
0
void KoskoStudy::makePath(QString path, QVector<int> &nowImg) {
	int lenOfNum;
	QVector<int> intPath;
	int leftBorder = 10000, upperBorder = -1000, rightBorder = -1000, bottomBorder = 10000, tmp;
	QVector<bool> isInc;
	while (path != "") {
		if (path[1] == '|') {
			isInc << 0;
			path = path.right(path.size() - 3);
			if (path == "")
				break;
		}
		else
			isInc << 1;
		lenOfNum = path.indexOf(",", 0);
		tmp = path.left(lenOfNum).toInt();
		intPath << tmp;
		if (tmp < leftBorder) {
			leftBorder = tmp;
		}
		if (tmp > rightBorder) {
			rightBorder = tmp;
		}
		path = path.right(path.size() - lenOfNum - 2);
		lenOfNum = path.indexOf(" ", 0);
		tmp = path.left(lenOfNum).toInt();
		intPath << tmp;
		if (tmp < bottomBorder) {
			bottomBorder = tmp;
		}
		if (tmp > upperBorder) {
			upperBorder = tmp;
		}
		path = path.right(path.size() - lenOfNum - 3);
	}
	int i;
	for (i = 0; i < intPath.size(); i += 2) {
		intPath[i] -= leftBorder;
		intPath[i + 1] -= bottomBorder;
	}
	nowImg.fill(0);
	int width = rightBorder - leftBorder + 1;
	int height = upperBorder - bottomBorder + 1;
	QVector<int> img (width * height, 0);
	for (i = 0; i < intPath.size() - 2; i += 2) {
		if (isInc[1 + i / 2]) {
			makeLine(intPath.at(i)
					 , intPath.at(i + 1)
					 , intPath.at(i + 2)
					 , intPath.at(i + 3)
					 , width
					 , height
					 , img
					 );
		}
	}
	int leftCM, rightCM, upperCM, bottomCM;
	makeMassCentres(img, width, height, leftCM, rightCM, upperCM, bottomCM);
	fitToSize(intPath, isInc, nowImg, leftCM, rightCM, upperCM, bottomCM);
	outp(nowImg);
}
Пример #26
0
void tst_ExceptionSafety::exceptionVector() {

    {
        QVector<FlexibleThrowerSmall> vector;
        QVector<FlexibleThrowerSmall> vector2;
        QVector<FlexibleThrowerSmall> vector3;

        for (int i = 0; i<10; i++)
            vector.append( FlexibleThrowerSmall(i) );

        try {
            throwType = ThrowAtCopy;
            vector.append( FlexibleThrowerSmall(10));
        } catch (...) {
        }
        QCOMPARE( vector.size(), 10 );

        try {
            throwType = ThrowAtCopy;
            vector.prepend( FlexibleThrowerSmall(10));
        } catch (...) {
        }
        QCOMPARE( vector.at(0).value(), 0 );
        QCOMPARE( vector.size(), 10 );

        try {
            throwType = ThrowAtCopy;
            vector.insert( 8, FlexibleThrowerSmall(10));
        } catch (...) {
        }
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.at(8).value(), 8 );
        QCOMPARE( vector.size(), 10 );

        try {
            throwType = ThrowAtCopy;
            vector3 = vector;
        } catch (...) {
        }
        QCOMPARE( vector.at(0).value(), 0 );
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.size(), 10 );
        QCOMPARE( vector3.at(0).value(), 0 );
        QCOMPARE( vector3.at(7).value(), 7 );
        QCOMPARE( vector3.size(), 10 );

        try {
            throwType = ThrowAtCopy;
            vector3.append( FlexibleThrowerSmall(11) );
        } catch (...) {
        }
        QCOMPARE( vector.at(0).value(), 0 );
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.size(), 10 );
        QCOMPARE( vector3.at(0).value(), 0 );
        QCOMPARE( vector3.at(7).value(), 7 );

        try {
            vector2.clear();
            vector2.append( FlexibleThrowerSmall(11));
            throwType = ThrowAtCopy;
            vector3 = vector+vector2;
        } catch (...) {
        }
        QCOMPARE( vector.at(0).value(), 0 );
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.size(), 10 );

        // check that copy on write works atomar
        vector2.clear();
        vector2.append( FlexibleThrowerSmall(11));
        vector3 = vector+vector2;
        try {
            throwType = ThrowAtCreate;
            vector3[7]=FlexibleThrowerSmall(12);
        } catch (...) {
        }
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.size(), 10 );
        QCOMPARE( vector3.at(7).value(), 7 );
        QCOMPARE( vector3.size(), 11 );

        try {
            throwType = ThrowAtCreate;
            vector.resize(15);
        } catch (...) {
        }
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.size(), 10 );

        try {
            throwType = ThrowAtCreate;
            vector.resize(15);
        } catch (...) {
        }
        QCOMPARE( vector.at(7).value(), 7 );
        QCOMPARE( vector.size(), 10 );

        try {
            throwType = ThrowLater;
            vector.fill(FlexibleThrowerSmall(1), 15);
        } catch (...) {
        }
        QCOMPARE( vector.at(0).value(), 0 );
        QCOMPARE( vector.size(), 10 );


    }
    QCOMPARE(objCounter, 0 ); // check that every object has been freed
}
Пример #27
0
void ModelTestWidget::showViewContextMenu(const QPoint &pos)
{
    const QModelIndex idx = m_handler->flatView()->indexAt(pos);
    if (!idx.isValid())
        return;

    QMenu menu;
    QAction *showCostItems = menu.addAction("show cost items");

    const ParseData* data = m_handler->dataModel()->parseData();

    QAction *ret = menu.exec(m_handler->flatView()->mapToGlobal(pos));
    if (ret == showCostItems) {
        ///TODO: put this into a reusable class?
        const Function *func = idx.data(DataModel::FunctionRole).value<const Function *>();
        Q_ASSERT(func);

        QTableView *view = new QTableView();
        view->setAttribute(Qt::WA_DeleteOnClose, true);
        const int rows = func->costItems().size();
        const int columns = data->events().size() + data->positions().size() + 2;
        QStandardItemModel *model = new QStandardItemModel(rows, columns, view);
        int headerColumn = 0;
        foreach (const QString &event, data->events()) {
            model->setHeaderData(headerColumn++, Qt::Horizontal, event);
        }
        const int lastEventColumn = headerColumn;
        foreach (const QString &pos, data->positions()) {
            model->setHeaderData(headerColumn++, Qt::Horizontal, pos);
        }
        const int lastPosColumn = headerColumn;
        model->setHeaderData(headerColumn++, Qt::Horizontal, "Call");
        model->setHeaderData(headerColumn++, Qt::Horizontal, "Differring File");
        Q_ASSERT(headerColumn == columns);

        QVector<quint64> totalCosts;
        totalCosts.fill(0, data->events().size());
        for (int row = 0; row < rows; ++row) {
            const CostItem *item = func->costItems().at(row);
            for (int column = 0; column < columns; ++column) {
                QVariant value;
                if (column < lastEventColumn) {
                    value = item->cost(column);
                    totalCosts[column] += item->cost(column);
                } else if (column < lastPosColumn) {
                    value = item->position(column - lastEventColumn);
                } else if (column == lastPosColumn) {
                    if (item->call())
                        value = item->call()->callee()->name();
                } else {
                    value = item->differingFile();
                }
                model->setData(model->index(row, column), value);
            }
        }
        QStringList totalCostsStrings;
        for (int i = 0; i < totalCosts.size(); ++i) {
            totalCostsStrings << QString("%1: %2").arg(totalCosts.at(i)).arg(data->events().at(i));
        }
        view->setWindowTitle(totalCostsStrings.join(QLatin1String(", ")));
        view->setModel(model);
        view->show();
    }
}
Пример #28
0
void counter(QVector<QVector<bool> > &results)
{
    QVector<bool> tempResult;

    tempResult.fill(false, 9);

    bool isWasLowerLimit = false;
    bool isWasUpperLimit = false;

    while(true) {
        if(tempResult.at(8) && tempResult.at(7) && tempResult.at(6) && tempResult.at(5)
                && tempResult.at(4) && tempResult.at(3) && tempResult.at(2) && tempResult.at(1)
                && tempResult.at(0)) {
            break;
        }
        if(tempResult.at(7) && tempResult.at(6) && tempResult.at(5) && tempResult.at(4)
                && tempResult.at(3) && tempResult.at(2) && tempResult.at(1) && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, false);
            tempResult.replace(3, false);
            tempResult.replace(4, false);
            tempResult.replace(5, false);
            tempResult.replace(6, false);
            tempResult.replace(7, false);
            tempResult.replace(8, true);
        }
        if(tempResult.at(6) && tempResult.at(5) && tempResult.at(4) && tempResult.at(3)
                && tempResult.at(2) && tempResult.at(1) && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, false);
            tempResult.replace(3, false);
            tempResult.replace(4, false);
            tempResult.replace(5, false);
            tempResult.replace(6, false);
            tempResult.replace(7, true);
        }
        if(tempResult.at(5) && tempResult.at(4) && tempResult.at(3) && tempResult.at(2)
                && tempResult.at(1) && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, false);
            tempResult.replace(3, false);
            tempResult.replace(4, false);
            tempResult.replace(5, false);
            tempResult.replace(6, true);
        }
        if(tempResult.at(4) && tempResult.at(3) && tempResult.at(2) && tempResult.at(1)
                && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, false);
            tempResult.replace(3, false);
            tempResult.replace(4, false);
            tempResult.replace(5, true);
        }
        if(tempResult.at(3) && tempResult.at(2) && tempResult.at(1) && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, false);
            tempResult.replace(3, false);
            tempResult.replace(4, true);
        }
        if(tempResult.at(2) && tempResult.at(1) && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, false);
            tempResult.replace(3, true);
        }
        if(tempResult.at(1) && tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, false);
            tempResult.replace(2, true);
        }
        if(tempResult.at(0)) {
            tempResult.replace(0, false);
            tempResult.replace(1, true);
        }

        qDebug() << "==========>";
        print(tempResult);
        qDebug() << "<==========";

        if(isEqual(tempResult, "111100000")) {
            qDebug() << "isWasLowerLimit" << isWasLowerLimit;
            isWasLowerLimit = true;
        }

        if(isEqual(tempResult, "100011111")) {
            qDebug() << "isWasUpperLimit" << isWasUpperLimit;
            isWasUpperLimit = true;
        }

        if(/*isWasLowerLimit && !isWasUpperLimit && */isValid(tempResult)) {
            results.push_back(tempResult);
        }

        tempResult.replace(0, true);

        if(/*isWasLowerLimit && !isWasUpperLimit && */isValid(tempResult)) {
            results.push_back(tempResult);
        }
    }
}
Пример #29
0
bool GLWidgetRendererPrivate::initTextures(const VideoFormat &fmt)
{
    // isSupported(pixfmt)
    if (!fmt.isValid())
        return false;
    video_format.setPixelFormatFFmpeg(fmt.pixelFormatFFmpeg());

    //http://www.berkelium.com/OpenGL/GDC99/internalformat.html
    //NV12: UV is 1 plane. 16 bits as a unit. GL_LUMINANCE4, 8, 16, ... 32?
    //GL_LUMINANCE, GL_LUMINANCE_ALPHA are deprecated in GL3, removed in GL3.1
    //replaced by GL_RED, GL_RG, GL_RGB, GL_RGBA? for 1, 2, 3, 4 channel image
    //http://www.gamedev.net/topic/634850-do-luminance-textures-still-exist-to-opengl/
    //https://github.com/kivy/kivy/issues/1738: GL_LUMINANCE does work on a Galaxy Tab 2. LUMINANCE_ALPHA very slow on Linux
    //ALPHA: vec4(1,1,1,A), LUMINANCE: (L,L,L,1), LUMINANCE_ALPHA: (L,L,L,A)
    /*
     * To support both planar and packed use GL_ALPHA and in shader use r,g,a like xbmc does.
     * or use Swizzle_mask to layout the channels: http://www.opengl.org/wiki/Texture#Swizzle_mask
     * GL ES2 support: GL_RGB, GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA
     * http://stackoverflow.com/questions/18688057/which-opengl-es-2-0-texture-formats-are-color-depth-or-stencil-renderable
     */
    if (!fmt.isPlanar()) {
        GLint internal_fmt;
        GLenum data_fmt;
        GLenum data_t;
        if (!OpenGLHelper::videoFormatToGL(fmt, &internal_fmt, &data_fmt, &data_t)) {
            qWarning("no opengl format found");
            return false;
        }
        internal_format = QVector<GLint>(fmt.planeCount(), internal_fmt);
        data_format = QVector<GLenum>(fmt.planeCount(), data_fmt);
        data_type = QVector<GLenum>(fmt.planeCount(), data_t);
    } else {
        internal_format.resize(fmt.planeCount());
        data_format.resize(fmt.planeCount());
        data_type = QVector<GLenum>(fmt.planeCount(), GL_UNSIGNED_BYTE);
        if (fmt.isPlanar()) {
            /*!
             * GLES internal_format == data_format, GL_LUMINANCE_ALPHA is 2 bytes
             * so if NV12 use GL_LUMINANCE_ALPHA, YV12 use GL_ALPHA
             */
            qDebug("///////////bpp %d", fmt.bytesPerPixel());
            internal_format[0] = data_format[0] = GL_LUMINANCE; //or GL_RED for GL
            if (fmt.planeCount() == 2) {
                internal_format[1] = data_format[1] = GL_LUMINANCE_ALPHA;
            } else {
                if (fmt.bytesPerPixel(1) == 2) {
                    // read 16 bits and compute the real luminance in shader
                    internal_format.fill(GL_LUMINANCE_ALPHA); //vec4(L,L,L,A)
                    data_format.fill(GL_LUMINANCE_ALPHA);
                } else {
                    internal_format[1] = data_format[1] = GL_LUMINANCE; //vec4(L,L,L,1)
                    internal_format[2] = data_format[2] = GL_ALPHA;//GL_ALPHA;
                }
            }
            for (int i = 0; i < internal_format.size(); ++i) {
                // xbmc use bpp not bpp(plane)
                //internal_format[i] = GetGLInternalFormat(data_format[i], fmt.bytesPerPixel(i));
                //data_format[i] = internal_format[i];
            }
        } else {
            //glPixelStorei(GL_UNPACK_ALIGNMENT, fmt.bytesPerPixel());
            // TODO: if no alpha, data_fmt is not GL_BGRA. align at every upload?
        }
    }
    for (int i = 0; i < fmt.planeCount(); ++i) {
        //qDebug("format: %#x GL_LUMINANCE_ALPHA=%#x", data_format[i], GL_LUMINANCE_ALPHA);
        if (fmt.bytesPerPixel(i) == 2 && fmt.planeCount() == 3) {
            //data_type[i] = GL_UNSIGNED_SHORT;
        }
        int bpp_gl = OpenGLHelper::bytesOfGLFormat(data_format[i], data_type[i]);
        int pad = qCeil((qreal)(texture_size[i].width() - effective_tex_width[i])/(qreal)bpp_gl);
        texture_size[i].setWidth(qCeil((qreal)texture_size[i].width()/(qreal)bpp_gl));
        texture_upload_size[i].setWidth(qCeil((qreal)texture_upload_size[i].width()/(qreal)bpp_gl));
        effective_tex_width[i] /= bpp_gl; //fmt.bytesPerPixel(i);
        //effective_tex_width_ratio =
        qDebug("texture width: %d - %d = pad: %d. bpp(gl): %d", texture_size[i].width(), effective_tex_width[i], pad, bpp_gl);
    }

    /*
     * there are 2 fragment shaders: rgb and yuv.
     * only 1 texture for packed rgb. planar rgb likes yuv
     * To support both planar and packed yuv, and mixed yuv(NV12), we give a texture sample
     * for each channel. For packed, each (channel) texture sample is the same. For planar,
     * packed channels has the same texture sample.
     * But the number of actural textures we upload is plane count.
     * Which means the number of texture id equals to plane count
     */
    if (textures.size() != fmt.planeCount()) {
        glDeleteTextures(textures.size(), textures.data());
        qDebug("delete %d textures", textures.size());
        textures.clear();
        textures.resize(fmt.planeCount());
        glGenTextures(textures.size(), textures.data());
    }

    if (!hasGLSL) {
        initTexture(textures[0], internal_format[0], data_format[0], data_type[0], texture_size[0].width(), texture_size[0].height());
        // more than 1?
        qWarning("Does not support GLSL!");
        return false;
    }
    qDebug("init textures...");
    for (int i = 0; i < textures.size(); ++i) {
        initTexture(textures[i], internal_format[i], data_format[i], data_type[i], texture_size[i].width(), texture_size[i].height());
    }
    return true;
}
Пример #30
0
int QgsStringUtils::levenshteinDistance( const QString& string1, const QString& string2, bool caseSensitive )
{
  int length1 = string1.length();
  int length2 = string2.length();

  //empty strings? solution is trivial...
  if ( string1.isEmpty() )
  {
    return length2;
  }
  else if ( string2.isEmpty() )
  {
    return length1;
  }

  //handle case sensitive flag (or not)
  QString s1( caseSensitive ? string1 : string1.toLower() );
  QString s2( caseSensitive ? string2 : string2.toLower() );

  const QChar* s1Char = s1.constData();
  const QChar* s2Char = s2.constData();

  //strip out any common prefix
  int commonPrefixLen = 0;
  while ( length1 > 0 && length2 > 0 && *s1Char == *s2Char )
  {
    commonPrefixLen++;
    length1--;
    length2--;
    s1Char++;
    s2Char++;
  }

  //strip out any common suffix
  while ( length1 > 0 && length2 > 0 && s1.at( commonPrefixLen + length1 - 1 ) == s2.at( commonPrefixLen + length2 - 1 ) )
  {
    length1--;
    length2--;
  }

  //fully checked either string? if so, the answer is easy...
  if ( length1 == 0 )
  {
    return length2;
  }
  else if ( length2 == 0 )
  {
    return length1;
  }

  //ensure the inner loop is longer
  if ( length1 > length2 )
  {
    qSwap( s1, s2 );
    qSwap( length1, length2 );
  }

  //levenshtein algorithm begins here
  QVector< int > col;
  col.fill( 0, length2 + 1 );
  QVector< int > prevCol;
  prevCol.reserve( length2 + 1 );
  for ( int i = 0; i < length2 + 1; ++i )
  {
    prevCol << i;
  }
  const QChar* s2start = s2Char;
  for ( int i = 0; i < length1; ++i )
  {
    col[0] = i + 1;
    s2Char = s2start;
    for ( int j = 0; j < length2; ++j )
    {
      col[j + 1] = qMin( qMin( 1 + col[j], 1 + prevCol[1 + j] ), prevCol[j] + (( *s1Char == *s2Char ) ? 0 : 1 ) );
      s2Char++;
    }
    col.swap( prevCol );
    s1Char++;
  }
  return prevCol[length2];
}