Beispiel #1
0
void SBTeam::checkBall() {
    Ball* ball = balls::getBall();
    if (ball) {
        if (!ball->isVisible()) {
            int waitCount(settings::C_iDumb*(botControllers_.size()+1)/200);
            for (int i=0; i<waitCount; ++i)
                addJob(Job(Job::jWaitForBall, 5, ball));
        }
        else {
            int ballZone(zones::isInside(this, *ball));
            switch (ballZone) {
                case OWN_HOME:
                    for (int i=0; i<botControllers_.size(); ++i)
                        addJob(Job(Job::jKickOutHome, 90, ball));
                    break;

                case OWN_TEAM: {
                    std::map<float, TacticalZone*> zones(zones::toProtect(this));
                    std::map<float, TacticalZone*>::iterator currentZone = zones.begin();
                    int protectJobs(botControllers_.size()*0.5);
                    while(protectJobs > 0) {
                        for (int i=0; i<(protectJobs+1)*0.5; ++i)
                            addJob(Job(Job::jProtectZone, 30,  currentZone->second));
                        protectJobs /= 2;
                        if (++currentZone == zones.end())
                            currentZone = zones.begin();
                    }
                    for (int i=botControllers_.size()*0.5f; i<botControllers_.size(); ++i)
                        addJob(Job(Job::jKickToEnemy, 60, ball));
                    for (int i=0; i<botControllers_.size()*0.5; ++i)
                        addJob(Job(Job::jKickOutHome, 40, ball));

                    break;
                }
                default: {
                    std::map<float, TacticalZone*> zones(zones::toProtect(this));
                    std::map<float, TacticalZone*>::iterator currentZone = zones.begin();
                    int protectJobs(botControllers_.size()*0.4);
                    while(protectJobs > 0) {
                        for (int i=0; i<(protectJobs+1)*0.5; ++i)
                            addJob(Job(Job::jProtectZone, 20,  currentZone->second));
                        protectJobs /= 2;
                        if (++currentZone == zones.end())
                            currentZone = zones.begin();
                    }
                    for (int i=0; i<botControllers_.size()*0.6f; ++i)
                        addJob(Job(Job::jKickToEnemy, 60, ball));
                }
            }
        }
    }
}
Beispiel #2
0
void
ZoneGroup::deleteEmptyZone(Zone* zone)
{
    MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime));
    MOZ_ASSERT(zone->group() == this);
    MOZ_ASSERT(zone->compartments().empty());
    for (auto& i : zones()) {
        if (i == zone) {
            zones().erase(&i);
            zone->destroy(runtime->defaultFreeOp());
            return;
        }
    }
    MOZ_CRASH("Zone not found");
}
Foam::wordList Foam::vtkPV4Foam::readZoneNames(const word& zoneType)
{
    wordList zoneNames;

    // mesh not loaded - read from file
    IOobject ioObj
    (
        zoneType,
        dbPtr_().findInstance
        (
            meshDir_,
            zoneType,
            IOobject::READ_IF_PRESENT
        ),
        meshDir_,
        dbPtr_(),
        IOobject::READ_IF_PRESENT,
        IOobject::NO_WRITE,
        false
    );

    if (ioObj.headerOk())
    {
        zonesEntries zones(ioObj);

        zoneNames.setSize(zones.size());
        forAll(zones, zoneI)
        {
            zoneNames[zoneI] = zones[zoneI].keyword();
        }
    }
Beispiel #4
0
void
Athlete::addRide(QString name, bool dosignal)
{
    QDateTime dt;
    if (!RideFile::parseRideFileName(name, &dt)) return;

    RideItem *last = new RideItem(RIDE_TYPE, home.path(), name, dt, zones(), hrZones(), context);

    int index = 0;
    while (index < allRides->childCount()) {
        QTreeWidgetItem *item = allRides->child(index);
        if (item->type() != RIDE_TYPE) continue;
        RideItem *other = static_cast<RideItem*>(item);

        if (other->dateTime > dt) break;
        if (other->fileName == name) {
            delete allRides->takeChild(index);
            break;
        }
        ++index;
    }
    if (dosignal) context->notifyRideAdded(last); // here so emitted BEFORE rideSelected is emitted!
    allRides->insertChild(index, last);

    // if it is the very first ride, we need to select it
    // after we added it
    if (!index) treeWidget->setCurrentItem(last);
}
Beispiel #5
0
/*
 * Find the location of the zoneinfo files and store in mZoneinfoDir.
 * Parse zone.tab and for each time zone, create a KSystemTimeZone instance.
 */
void KSystemTimeZonesPrivate::readZoneTab(bool update)
{
    kDebug(161) << "readZoneTab(" << m_zonetab<< ")";
    QStringList newZones;
    QFile f;
    f.setFileName(m_zonetab);
    if (!f.open(QIODevice::ReadOnly))
        return;
    QTextStream str(&f);
    QRegExp lineSeparator("[ \t]");
    QRegExp ordinateSeparator("[+-]");
    if (!m_source)
        m_source = new KSystemTimeZoneSource;
    while (!str.atEnd())
    {
        QString line = str.readLine();
        if (line.isEmpty() || line[0] == '#')
            continue;
        QStringList tokens = KStringHandler::perlSplit(lineSeparator, line, 4);
        int n = tokens.count();
        if (n < 3)
        {
            kError(161) << "readZoneTab(): invalid record: " << line << endl;
            continue;
        }

        // Got three tokens. Now check for two ordinates plus first one is "".
        int i = tokens[1].indexOf(ordinateSeparator, 1);
        if (i < 0)
        {
            kError(161) << "readZoneTab() " << tokens[2] << ": invalid coordinates: " << tokens[1] << endl;
            continue;
        }

        float latitude = convertCoordinate(tokens[1].left(i));
        float longitude = convertCoordinate(tokens[1].mid(i));

        // Add entry to list.
        if (tokens[0] == "??")
            tokens[0] = "";
        // Solaris sets the empty Comments field to '-', making it not empty.
        // Clean it up.
        if (n > 3  &&  tokens[3] == "-")
            tokens[3] = "";
        KSystemTimeZone tz(m_source, tokens[2], tokens[0], latitude, longitude, (n > 3 ? tokens[3] : QString()));
        if (update)
        {
            // Update the existing collection with the new zone definition
            newZones += tz.name();
            KTimeZone oldTz = zone(tz.name());
            if (oldTz.isValid())
                oldTz.updateBase(tz);   // the zone previously existed, so update its definition
            else
                add(tz);   // the zone didn't previously exist, so add it
        }
        else
            add(tz);
    }
    f.close();

    if (update)
    {
        // Remove any zones from the collection which no longer exist
        const ZoneMap oldZones = zones();
        for (ZoneMap::ConstIterator it = oldZones.constBegin();  it != oldZones.constEnd();  ++it)
        {
            if (newZones.indexOf(it.key()) < 0)
                remove(it.value());
        }
    }
}
Beispiel #6
0
Athlete::Athlete(Context *context, const QDir &home)
{
    // athlete name
    this->home = home;
    this->context = context;
    context->athlete = this;
    cyclist = home.dirName();
    isclean = false;

    // Recovering from a crash?
    if(!appsettings->cvalue(cyclist, GC_SAFEEXIT, true).toBool()) {
        GcCrashDialog *crashed = new GcCrashDialog(home);
        crashed->exec();
    }
    appsettings->setCValue(cyclist, GC_SAFEEXIT, false); // will be set to true on exit

    // Before we initialise we need to run the upgrade wizard for this athlete
    GcUpgrade v3;
    v3.upgrade(context->athlete->home);

    // metric / non-metric
    QVariant unit = appsettings->cvalue(cyclist, GC_UNIT);
    if (unit == 0) {
        // Default to system locale
        unit = appsettings->value(this, GC_UNIT,
             QLocale::system().measurementSystem() == QLocale::MetricSystem ? GC_UNIT_METRIC : GC_UNIT_IMPERIAL);
        appsettings->setCValue(cyclist, GC_UNIT, unit);
    }
    useMetricUnits = (unit.toString() == GC_UNIT_METRIC);

    // Power Zones
    zones_ = new Zones;
    QFile zonesFile(home.absolutePath() + "/power.zones");
    if (zonesFile.exists()) {
        if (!zones_->read(zonesFile)) {
            QMessageBox::critical(context->mainWindow, tr("Zones File Error"),
				  zones_->errorString());
        } else if (! zones_->warningString().isEmpty())
            QMessageBox::warning(context->mainWindow, tr("Reading Zones File"), zones_->warningString());
    }

    // Heartrate Zones
    hrzones_ = new HrZones;
    QFile hrzonesFile(home.absolutePath() + "/hr.zones");
    if (hrzonesFile.exists()) {
        if (!hrzones_->read(hrzonesFile)) {
            QMessageBox::critical(context->mainWindow, tr("HR Zones File Error"),
				  hrzones_->errorString());
        } else if (! hrzones_->warningString().isEmpty())
            QMessageBox::warning(context->mainWindow, tr("Reading HR Zones File"), hrzones_->warningString());
    }

    // read athlete's charts.xml and translate etc
    LTMSettings reader;
    reader.readChartXML(context->athlete->home, context->athlete->useMetricUnits, presets);
    translateDefaultCharts(presets);

    // Metadata
    rideMetadata_ = new RideMetadata(context,true);
    rideMetadata_->hide();

    // Date Ranges
    seasons = new Seasons(home);

    // Search / filter
#ifdef GC_HAVE_LUCENE
    namedSearches = new NamedSearches(this); // must be before navigator
    lucene = new Lucene(context, context); // before metricDB attempts to refresh
#endif

    // metrics DB
    metricDB = new MetricAggregator(context); // just to catch config updates!
    metricDB->refreshMetrics();

    // the model atop the metric DB
    sqlModel = new QSqlTableModel(this, metricDB->db()->connection());
    sqlModel->setTable("metrics");
    sqlModel->setEditStrategy(QSqlTableModel::OnManualSubmit);

    // Downloaders
    withingsDownload = new WithingsDownload(context);
    zeoDownload      = new ZeoDownload(context);
    calendarDownload = new CalendarDownload(context);

    // Calendar
#ifdef GC_HAVE_ICAL
    rideCalendar = new ICalendar(context); // my local/remote calendar entries
    davCalendar = new CalDAV(context); // remote caldav
    davCalendar->download(); // refresh the diary window
#endif

    // RIDE TREE -- transitionary
    treeWidget = new QTreeWidget;
    treeWidget->setColumnCount(3);
    treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    treeWidget->header()->resizeSection(0,60);
    treeWidget->header()->resizeSection(1,100);
    treeWidget->header()->resizeSection(2,70);
    treeWidget->header()->hide();
    treeWidget->setAlternatingRowColors (false);
    treeWidget->setIndentation(5);
    treeWidget->hide();

    allRides = new QTreeWidgetItem(context->athlete->treeWidget, FOLDER_TYPE);
    allRides->setText(0, tr("All Activities"));
    treeWidget->expandItem(context->athlete->allRides);
    treeWidget->setFirstItemColumnSpanned (context->athlete->allRides, true);

    //.INTERVALS TREE -- transitionary
    intervalWidget = new IntervalTreeView(context);
    intervalWidget->setColumnCount(1);
    intervalWidget->setIndentation(5);
    intervalWidget->setSortingEnabled(false);
    intervalWidget->header()->hide();
    intervalWidget->setAlternatingRowColors (false);
    intervalWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    intervalWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    intervalWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
    intervalWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    intervalWidget->setFrameStyle(QFrame::NoFrame);
    allIntervals = context->athlete->intervalWidget->invisibleRootItem();
    allIntervals->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
    allIntervals->setText(0, tr("Intervals"));

    // populate ride list
    QTreeWidgetItem *last = NULL;
    QStringListIterator i(RideFileFactory::instance().listRideFiles(home));
    while (i.hasNext()) {
        QString name = i.next();
        QDateTime dt;
        if (RideFile::parseRideFileName(name, &dt)) {
            last = new RideItem(RIDE_TYPE, home.path(), name, dt, zones(), hrZones(), context);
            allRides->addChild(last);
        }
    }

    // trap signals
    connect(context, SIGNAL(configChanged()), this, SLOT(configChanged()));
    connect(treeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(rideTreeWidgetSelectionChanged()));
    connect(context,SIGNAL(rideAdded(RideItem*)),this,SLOT(checkCPX(RideItem*)));
    connect(context,SIGNAL(rideDeleted(RideItem*)),this,SLOT(checkCPX(RideItem*)));
    connect(intervalWidget,SIGNAL(itemSelectionChanged()), this, SLOT(intervalTreeWidgetSelectionChanged()));
    connect(intervalWidget,SIGNAL(itemChanged(QTreeWidgetItem *,int)), this, SLOT(updateRideFileIntervals()));
}
bool Foam::fileFormats::VTKsurfaceFormat<Face>::read
(
    const fileName& filename
)
{
    const bool mustTriangulate = this->isTri();
    this->clear();

    IFstream is(filename);
    if (!is.good())
    {
        FatalErrorInFunction
            << "Cannot read file " << filename
            << exit(FatalError);
    }

    // assume that the groups are not intermixed
    bool sorted = true;


    // Construct dummy time so we have something to create an objectRegistry
    // from
    Time dummyTime
    (
        "dummyRoot",
        "dummyCase",
        "system",
        "constant",
        false           // enableFunctionObjects
    );

    // Make dummy object registry
    objectRegistry obr
    (
        IOobject
        (
            "dummy",
            dummyTime,
            IOobject::NO_READ,
            IOobject::NO_WRITE,
            false
        )
    );

    // Read all
    vtkUnstructuredReader reader(obr, is);
    const faceList& faces = reader.faces();

    // Assume all faces in zone0 unless a region field is present
    labelList zones(faces.size(), 0);
    if (reader.cellData().foundObject<scalarIOField>("region"))
    {
        const scalarIOField& region =
            reader.cellData().lookupObject<scalarIOField>
            (
                "region"
            );
        forAll(region, i)
        {
            zones[i] = label(region[i]);
        }
    }
Beispiel #8
0
lInterestPoints HarrisPointDetector::computeInterestPoints(KisPaintDeviceSP device, const QRect& rect)
// lHarrisPoints computeHarrisPoints(KisPaintDeviceSP device, QRect rect)
{
    dbgPlugins << "Compute Harris points on the rect :" << rect;
    Q_ASSERT(device->colorSpace()->id() == "GRAYA");
    lInterestPoints points;

    // Compute the derivatives
    KisEightFloatColorSpace* floatCs = new KisEightFloatColorSpace();
    KisPaintDeviceSP infoDevice = new KisPaintDevice(floatCs, "infoDevice");

    float g_var = DERIVATION_SIGMA * DERIVATION_SIGMA ;
    float sqrt2pi = sqrt(2 * M_PI);
    float beta0 = 1 / (sqrt2pi * DERIVATION_SIGMA);

    float beta1 = beta0 * exp(-1 / (2 * g_var));
    float beta2 = beta0 * exp(-4 / (2 * g_var));

    float alpha1 = beta1 / g_var;
    float alpha2 = 2 * beta2 / g_var;



    {
        KisHLineConstIteratorPixel hitDevice = device->createHLineConstIterator(rect.left(), rect.top() + 2, rect.width() - 4);
        KisHLineIteratorPixel hitinfoDevice = infoDevice-> createHLineIterator(rect.left() + 2, 2, rect.width());

        quint8 pixelvalue[5];

        dbgPlugins << " Compute the derivatives";
        dbgPlugins << "  horizontal derivatives";
        /* Horizontal computation of derivatives */
        for (int y = rect.top() + 2; y < rect.bottom() - 2; y++) {
            pixelvalue[LEFTLEFT] = *hitDevice.rawData();
            ++hitDevice;
            pixelvalue[LEFT] = *hitDevice.rawData();
            ++hitDevice;
            pixelvalue[CENTER] = *hitDevice.rawData();
            ++hitDevice;
            pixelvalue[RIGHT] = *hitDevice.rawData();
            ++hitDevice;
            while (!hitDevice.isDone()) {
                pixelvalue[RIGHTRIGHT] = *hitDevice.rawData();
                float* infoValues = reinterpret_cast<float*>(hitinfoDevice.rawData());
                infoValues[INFO_HDIFF] = alpha1 * (pixelvalue[LEFT] - pixelvalue[RIGHT]) + alpha2 * (pixelvalue[LEFTLEFT] - pixelvalue[RIGHTRIGHT]);
                infoValues[INFO_HADD] = beta0 * (pixelvalue[CENTER]) + beta1 * (pixelvalue[LEFT] + pixelvalue[RIGHT]) + beta2 * (pixelvalue[LEFTLEFT] + pixelvalue[RIGHTRIGHT]);
                infoValues[INFO_INTENSITY] = pixelvalue[CENTER];
//                     dbgPlugins << hitDevice.x() <<"" << hitDevice.y() <<"" << infoValues[INFO_HDIFF] <<"" << infoValues[INFO_HADD] <<"" << (int)pixelvalue[CENTER] <<"" << infoValues[INFO_INTENSITY];
                memmove(pixelvalue, pixelvalue + 1, 4*sizeof(quint8));
                ++hitDevice;
                ++hitinfoDevice;
            }
            hitDevice.nextRow();
            hitinfoDevice.nextRow();
        }
    }

    KisTransaction a("", infoDevice);
    {
        KisVLineConstIteratorPixel vitinfoDeviceRead = infoDevice-> createVLineConstIterator(rect.left() + 4, rect.top(), rect.height());
        KisVLineIteratorPixel vitinfoDevice = infoDevice-> createVLineIterator(rect.left() + 4, rect.top() + 2, rect.height() - 2);

        float hdiffValue[5];
        float haddValue[5];
        dbgPlugins << "  vertical derivatives";
        /* Vertical computation of derivatives */
        for (int x = rect.left() + 4; x < rect.right() - 4; x++) {
            const float* infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[TOPTOP] = infoValue[INFO_HDIFF];
            haddValue[TOPTOP] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;
            infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[TOP] = infoValue[INFO_HDIFF];
            haddValue[TOP] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;
            infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[CENTER] = infoValue[INFO_HDIFF];
            haddValue[CENTER] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;
            infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
            hdiffValue[RIGHT] = infoValue[INFO_HDIFF];
            haddValue[RIGHT] = infoValue[INFO_HADD];
            ++vitinfoDeviceRead;

            while (!vitinfoDevice.isDone()) {
                infoValue = reinterpret_cast<const float*>(vitinfoDeviceRead.oldRawData());
                hdiffValue[RIGHTRIGHT] = infoValue[INFO_HDIFF];
                haddValue[RIGHTRIGHT] = infoValue[INFO_HADD];

                float c_grdy = beta0 * hdiffValue[ CENTER ] + beta1 * (hdiffValue[ TOP ] + hdiffValue[ BOTTOM ]) + beta2 * (hdiffValue[ TOPTOP ] + hdiffValue[ BOTTOMBOTTOM ]);
                float c_grdx = alpha1 * (haddValue[ TOP ] - haddValue[ BOTTOM ]) + alpha2 * (haddValue[ TOPTOP ] - haddValue[ BOTTOMBOTTOM ]);

                float* infoValueDst = reinterpret_cast<float*>(vitinfoDevice.rawData());
                infoValueDst[ INFO_XX ] = c_grdx * c_grdx;
                infoValueDst[ INFO_YY ] = c_grdy * c_grdy;
                infoValueDst[ INFO_X ] = c_grdx;
                infoValueDst[ INFO_Y ] = c_grdy;
                infoValueDst[ INFO_XY ] = c_grdx * c_grdy;

                memmove(hdiffValue, hdiffValue + 1, 4 * sizeof(float));
                memmove(haddValue , haddValue + 1 , 4 * sizeof(float));
                ++vitinfoDeviceRead;
                ++vitinfoDevice;
            }
            vitinfoDeviceRead.nextCol();
            vitinfoDevice.nextCol();
        }
    }

    // Apply a blur

    // Apply a blur
    KisTransaction("", infoDevice);

#if 1
    {
        KisHLineConstIteratorPixel hitDevice = infoDevice->createHLineConstIterator(rect.left(), rect.top() + 2, rect.width() - 4);
        KisHLineIteratorPixel hitinfoDevice = infoDevice-> createHLineIterator(rect.left() + 2, rect.top() + 2, rect.width() - 4);

        float pixelvalue[6][6];

        dbgPlugins << " Compute the blur";
        dbgPlugins << "  horizontal blur";
        /* Horizontal computation of derivatives */
        for (int y = rect.top() + 2; y < rect.bottom() - 2; y++) {
            memcpy(pixelvalue[LEFTLEFT], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            memcpy(pixelvalue[LEFT], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            memcpy(pixelvalue[CENTER], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            memcpy(pixelvalue[RIGHT], hitDevice.rawData(), 6*sizeof(float));
            ++hitDevice;
            while (!hitDevice.isDone()) {
                memcpy(pixelvalue[RIGHTRIGHT], hitDevice.rawData(), 6*sizeof(float));
                float* infoValues = reinterpret_cast<float*>(hitinfoDevice.rawData());
                for (int i = 0; i < 5; i++) {
                    infoValues[i] = beta0 *  pixelvalue[CENTER][i] + beta1 * (pixelvalue[LEFT][i] + pixelvalue[RIGHT][i]) + beta2 * (pixelvalue[LEFTLEFT][i] + pixelvalue[RIGHTRIGHT][i]);
//                   infoValues[i] =2 *  pixelvalue[CENTER][i] + ( pixelvalue[LEFT][i] + pixelvalue[RIGHT][i] );
                }
//                 memmove(pixelvalue, pixelvalue + 1, 4*sizeof(float[6]));
                for (int i = 0; i < 5; i++) {
                    memcpy(pixelvalue[i], pixelvalue[i+1], 6*sizeof(float));
                }
                ++hitDevice;
                ++hitinfoDevice;
            }
            hitDevice.nextRow();
            hitinfoDevice.nextRow();
        }
    }
    KisTransaction b("", infoDevice);
    {
        KisVLineConstIteratorPixel vitinfoDeviceRead = infoDevice-> createVLineConstIterator(rect.left() + 4, rect.top(), rect.height());
        KisVLineIteratorPixel vitinfoDevice = infoDevice-> createVLineIterator(rect.left() + 4, rect.top() + 2, rect.height() - 4);

        float infoValue[6][6];
        dbgPlugins << "  vertical blur";
        /* Vertical computation of derivatives */
        for (int x = rect.left() + 4; x < rect.right() - 4; x++) {
            memcpy(infoValue[TOPTOP], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            memcpy(infoValue[TOP], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            memcpy(infoValue[CENTER], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            memcpy(infoValue[BOTTOM], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
            ++vitinfoDeviceRead;
            while (!vitinfoDevice.isDone()) {
                memcpy(infoValue[BOTTOMBOTTOM], vitinfoDeviceRead.oldRawData(), 6*sizeof(float));
                float* dst = reinterpret_cast<float*>(vitinfoDevice.rawData());
                for (int i = 0; i < 5; i++) {
                    dst[i] =  beta0 * infoValue[CENTER][i] + beta1 * (infoValue[BOTTOM][i] + infoValue[TOP][i]) + beta2 * (infoValue[TOPTOP][i] + infoValue[BOTTOMBOTTOM][i]);
//                   dst[i] =  (2*infoValue[CENTER][i] + ( infoValue[BOTTOM][i] + infoValue[TOP][i] )) / 16;
                }
//                 memmove(infoValue, infoValue + 1, 4*sizeof(float[6]));
                for (int i = 0; i < 5; i++) {
                    memcpy(infoValue[i], infoValue[i+1], 6*sizeof(float));
                }
                ++vitinfoDeviceRead;
                ++vitinfoDevice;
            }
            vitinfoDeviceRead.nextCol();
            vitinfoDevice.nextCol();
        }
    }
#endif

#if 0
    KisTransaction("", infoDevice);
    dbgPlugins << " Blur";
    {
        // Compute the blur mask
        KisAutobrushShape* kas = new KisAutobrushCircleShape(5, 5, 2, 2);

        QImage mask;
        kas->createBrush(&mask);
        KisKernelSP kernel = KisKernel::fromQImage(mask);
        // Apply the convolution to xxDevice
        KisConvolutionPainter infoDevicePainter(infoDevice);
        infoDevicePainter.beginTransaction("bouuh");
        infoDevicePainter.applyMatrix(kernel, 2, 2, rect.width() - 4, rect.height() - 4, BORDER_REPEAT);
        delete kas;
    }
#endif
    dbgPlugins << " compute curvatures";
    // Compute the curvatures
    {
        KisRectIteratorPixel vitinfoDeviceRect = infoDevice->createRectIterator(2, 0, rect.width() - 2, rect.height() - 2);
        for (;!vitinfoDeviceRect.isDone(); ++vitinfoDeviceRect) {
            float* infoValue = reinterpret_cast<float*>(vitinfoDeviceRect.rawData());

            float det = infoValue[INFO_XX] * infoValue[INFO_YY] - infoValue[INFO_XY] * infoValue[INFO_XY];
            float trace = infoValue[INFO_XX] + infoValue[INFO_YY];
            float temp = sqrt(trace * trace - 4 * det);

            infoValue[ INFO_HIGH ] = 0.5 * (trace + temp);
            infoValue[ INFO_LOW  ] = 0.5 * (trace - temp);
            if (infoValue[ INFO_HIGH ] < infoValue[ INFO_LOW  ]) {
                float a = infoValue[ INFO_HIGH ];
                infoValue[ INFO_HIGH ] = infoValue[ INFO_LOW ];
                infoValue[ INFO_LOW ] = a;
            }
//                 dbgPlugins << vitinfoDeviceRect.x() <<"" << vitinfoDeviceRect.y() <<"" << infoValue[INFO_XX] <<"" << infoValue[INFO_YY]  <<"" << infoValue[INFO_XY] <<"" << infoValue[INFO_HIGH] <<"" << infoValue[INFO_LOW] <<"" << trace <<"" << temp <<"" << det;
        }
    }
    HarrisPoints zones(5, 5, rect.width(), rect.height(), FEATURES_QUANTITY);
    // Detect Harris Points
    {
        int margin = 8;
        KisHLineIterator hitinfoDevice = infoDevice-> createHLineIterator(margin, margin, rect.width() - 2 * margin);
        for (int y = margin + rect.top(); y < rect.bottom() - margin; y++) {
            for (int x = margin + rect.left(); x < rect.right() - margin; x++, ++hitinfoDevice) {
                float* infoValue = reinterpret_cast<float*>(hitinfoDevice.rawData());
                float low = infoValue[ INFO_LOW ];
//                     dbgPlugins << low;
                if (low > THRESHOLD_LAMBDA) {
                    KisRectIteratorPixel vitinfoDeviceRect = infoDevice->createRectIterator(x - 1, y - 1, 3, 3);
                    bool greater = true;
                    for (;!vitinfoDeviceRect.isDone(); ++vitinfoDeviceRect) {
                        if (reinterpret_cast<float*>(vitinfoDeviceRect.rawData())[ INFO_LOW ] > low) {
                            greater = false;
                            break;
                        }
                    }
                    if (greater) {
//                             dbgPlugins <<"new point";
                        HarrisPoint* hp = new HarrisPoint(x, y, infoValue[INFO_INTENSITY], infoValue[INFO_HIGH], infoValue[INFO_LOW], device);
#if 0
                        points.push_back(hp);
#endif
#if 0
                        if (points.empty()) {
                            points.push_back(hp);
                        } else {
                            if (points.size() >= FEATURES_QUANTITY && hp->low() > static_cast<HarrisPoint*>(points.back())->low()) { // remove last element, the totalNumber stay equal to FEATURES_QUANTITY
                                points.pop_back();
                            }
                            if (points.size() != FEATURES_QUANTITY) {
                                lInterestPoints::iterator it;
                                if (hp->low() < static_cast<HarrisPoint*>(points.back())->low()) {
                                    points.push_back(hp);
                                } else {
                                    // insert the new corner at his right place
                                    bool inserted = false;
                                    for (it = points.begin(); it != points.end(); it++) {
                                        if (hp->low() >= static_cast<HarrisPoint*>(*it)->low()) {
                                            //                                             dbgPlugins <<"insert point";
                                            points.insert(it, hp);
                                            inserted = true;
                                            break;
                                        }
                                    }
                                    if (!inserted) delete hp;
                                }
                            } else { // hp wasn't added to the list, remove it
                                delete hp;
                            }
                        }
#endif
#if 1
                        zones.instertPoint(hp);
#endif
                    }
                }
            }
            hitinfoDevice.nextRow();
        }
    }
    points = zones.points();
    dbgPlugins << "Harris detector has found :" << points.size() << " harris points";

    delete floatCs;
    return points;
}
QVariantMap QgsZonalHistogramAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{

  std::unique_ptr< QgsFeatureSource > zones( parameterAsSource( parameters, QStringLiteral( "INPUT_VECTOR" ), context ) );
  if ( !zones )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT_VECTOR" ) ) );

  long count = zones->featureCount();
  double step = count > 0 ? 100.0 / count : 1;
  long current = 0;

  QList< double > uniqueValues;
  QMap< QgsFeatureId, QHash< double, qgssize > > featuresUniqueValues;

  // First loop through the zones to build up a list of unique values across all zones to determine sink fields list
  QgsFeatureRequest request;
  request.setNoAttributes();
  if ( zones->sourceCrs() != mCrs )
  {
    request.setDestinationCrs( mCrs, context.transformContext() );
  }
  QgsFeatureIterator it = zones->getFeatures( request );
  QgsFeature f;
  while ( it.nextFeature( f ) )
  {
    if ( feedback && feedback->isCanceled() )
    {
      break;
    }
    feedback->setProgress( current * step );

    if ( !f.hasGeometry() )
    {
      current++;
      continue;
    }

    QgsGeometry featureGeometry = f.geometry();
    QgsRectangle featureRect = featureGeometry.boundingBox().intersect( mRasterExtent );
    if ( featureRect.isEmpty() )
    {
      current++;
      continue;
    }

    int nCellsX, nCellsY;
    QgsRectangle rasterBlockExtent;
    QgsRasterAnalysisUtils::cellInfoForBBox( mRasterExtent, featureRect, mCellSizeX, mCellSizeY, nCellsX, nCellsY, mNbCellsXProvider, mNbCellsYProvider, rasterBlockExtent );

    QHash< double, qgssize > fUniqueValues;
    QgsRasterAnalysisUtils::statisticsFromMiddlePointTest( mRasterInterface.get(), mRasterBand, featureGeometry, nCellsX, nCellsY, mCellSizeX, mCellSizeY,
    rasterBlockExtent, [ &fUniqueValues]( double value ) { fUniqueValues[value]++; }, false );

    if ( fUniqueValues.count() < 1 )
    {
      // The cell resolution is probably larger than the polygon area. We switch to slower precise pixel - polygon intersection in this case
      // TODO: eventually deal with weight if needed
      QgsRasterAnalysisUtils::statisticsFromPreciseIntersection( mRasterInterface.get(), mRasterBand, featureGeometry, nCellsX, nCellsY, mCellSizeX, mCellSizeY,
      rasterBlockExtent, [ &fUniqueValues]( double value, double ) { fUniqueValues[value]++; }, false );
    }

    for ( auto it = fUniqueValues.constBegin(); it != fUniqueValues.constEnd(); ++it )
    {
      if ( uniqueValues.indexOf( it.key() ) == -1 )
      {
        uniqueValues << it.key();
      }
      featuresUniqueValues[f.id()][it.key()] += it.value();
    }

    current++;
  }

  std::sort( uniqueValues.begin(), uniqueValues.end() );

  QString fieldPrefix = parameterAsString( parameters, QStringLiteral( "COLUMN_PREFIX" ), context );
  QgsFields newFields;
  for ( auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
  {
    newFields.append( QgsField( QStringLiteral( "%1%2" ).arg( fieldPrefix, mHasNoDataValue && *it == mNodataValue ? QStringLiteral( "NODATA" ) : QString::number( *it ) ), QVariant::LongLong, QString(), -1, 0 ) );
  }
  QgsFields fields = QgsProcessingUtils::combineFields( zones->fields(), newFields );

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields,
                                          zones->wkbType(), zones->sourceCrs() ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  it = zones->getFeatures( QgsFeatureRequest() );
  while ( it.nextFeature( f ) )
  {
    QgsAttributes attributes = f.attributes();
    QHash< double, qgssize > fUniqueValues = featuresUniqueValues.value( f.id() );
    for ( auto it = uniqueValues.constBegin(); it != uniqueValues.constEnd(); ++it )
    {
      attributes += fUniqueValues.value( *it, 0 );
    }

    QgsFeature outputFeature;
    outputFeature.setGeometry( f.geometry() );
    outputFeature.setAttributes( attributes );

    sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
  }

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  return outputs;
}