void Layer::joinConnectedFeatures() { // go through all label texts QString labelText; while ( !connectedTexts->isEmpty() ) { labelText = connectedTexts->takeFirst(); //std::cerr << "JOIN: " << labelText << std::endl; QHash< QString, QLinkedList<FeaturePart*>* >::const_iterator partsPtr = connectedHashtable->find( labelText ); if ( partsPtr == connectedHashtable->constEnd() ) continue; // shouldn't happen QLinkedList<FeaturePart*>* parts = *partsPtr; // go one-by-one part, try to merge while ( !parts->isEmpty() ) { // part we'll be checking against other in this round FeaturePart* partCheck = parts->takeFirst(); FeaturePart* otherPart = _findConnectedPart( partCheck, parts ); if ( otherPart ) { //std::cerr << "- connected " << partCheck << " with " << otherPart << std::endl; // remove partCheck from r-tree double bmin[2], bmax[2]; partCheck->getBoundingBox( bmin, bmax ); rtree->Remove( bmin, bmax, partCheck ); featureParts->removeOne( partCheck ); otherPart->getBoundingBox( bmin, bmax ); // merge points from partCheck to p->item if ( otherPart->mergeWithFeaturePart( partCheck ) ) { // reinsert p->item to r-tree (probably not needed) rtree->Remove( bmin, bmax, otherPart ); otherPart->getBoundingBox( bmin, bmax ); rtree->Insert( bmin, bmax, otherPart ); } } } // we're done processing feature parts with this particular label text delete parts; } // we're done processing connected fetures delete connectedHashtable; connectedHashtable = NULL; delete connectedTexts; connectedTexts = NULL; }
//static CoverArt CoverArtUtils::selectCoverArtForTrack( Track* pTrack, const QLinkedList<QFileInfo>& covers) { if (pTrack == NULL || covers.isEmpty()) { CoverArt art; art.info.source = CoverInfo::GUESSED; return art; } const QString trackBaseName = pTrack->getFileInfo().baseName(); const QString albumName = pTrack->getAlbum(); return selectCoverArtForTrack(trackBaseName, albumName, covers); }
QLinkedList<const GEOSGeometry *>* pal::Util::unmulti( const GEOSGeometry *the_geom ) { QLinkedList<const GEOSGeometry*> *queue = new QLinkedList<const GEOSGeometry*>; QLinkedList<const GEOSGeometry*> *final_queue = new QLinkedList<const GEOSGeometry*>; const GEOSGeometry *geom; queue->append( the_geom ); int nGeom; int i; GEOSContextHandle_t geosctxt = geosContext(); while ( !queue->isEmpty() ) { geom = queue->takeFirst(); int type = GEOSGeomTypeId_r( geosctxt, geom ); switch ( type ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: nGeom = GEOSGetNumGeometries_r( geosctxt, geom ); for ( i = 0; i < nGeom; i++ ) { queue->append( GEOSGetGeometryN_r( geosctxt, geom, i ) ); } break; case GEOS_POINT: case GEOS_LINESTRING: case GEOS_POLYGON: final_queue->append( geom ); break; default: QgsDebugMsg( QString( "unexpected geometry type:%1" ).arg( type ) ); delete final_queue; delete queue; return nullptr; } } delete queue; return final_queue; }
void AssignLayers::run(Graph &graph) { emit setStatusMsg("Assigning layers..."); // copy the nodes to a linked list QLinkedList<AbstractNode*> vertices; for(AbstractNode* v : graph.getNodes()) { vertices.append(v); } QSet<AbstractNode*> U; QSet<AbstractNode*> Z; QList<QList<AbstractNode*>> layers; //add the first layer int currentLayer = 0; layers.append(QList<AbstractNode*>()); while(!vertices.isEmpty()) { AbstractNode* selected = nullptr; for(AbstractNode* v : vertices) { if(Z.contains(v->getPredecessors().toSet())) { selected = v; break; } } if(selected != nullptr) { selected->setLayer(currentLayer); layers.last().append(selected); U.insert(selected); vertices.removeOne(selected); } else { currentLayer++; layers.append(QList<AbstractNode*>()); Z.unite(U); } } graph.setLayers(layers); graph.repaintLayers(); emit setStatusMsg("Assigning layers... Done!"); }
void PluckerGenerator::generatePixmap( Okular::PixmapRequest * request ) { const QSizeF size = mPages[ request->pageNumber() ]->size(); QPixmap *pixmap = new QPixmap( request->width(), request->height() ); pixmap->fill( Qt::white ); QPainter p; p.begin( pixmap ); qreal width = request->width(); qreal height = request->height(); p.scale( width / (qreal)size.width(), height / (qreal)size.height() ); mPages[ request->pageNumber() ]->drawContents( &p ); p.end(); request->page()->setPixmap( request->id(), pixmap ); if ( !mLinkAdded.contains( request->pageNumber() ) ) { QLinkedList<Okular::ObjectRect*> objects; for ( int i = 0; i < mLinks.count(); ++i ) { if ( mLinks[ i ].page == request->pageNumber() ) { QTextDocument *document = mPages[ request->pageNumber() ]; QRectF rect; calculateBoundingRect( document, mLinks[ i ].start, mLinks[ i ].end, rect ); objects.append( new Okular::ObjectRect( rect.left(), rect.top(), rect.right(), rect.bottom(), false, Okular::ObjectRect::Action, mLinks[ i ].link ) ); } } if ( !objects.isEmpty() ) request->page()->setObjectRects( objects ); mLinkAdded.insert( request->pageNumber() ); } signalPixmapRequestDone( request ); }
QLinkedList<const GEOSGeometry *> *unmulti( const GEOSGeometry *the_geom ) { QLinkedList<const GEOSGeometry*> *queue = new QLinkedList<const GEOSGeometry*>; QLinkedList<const GEOSGeometry*> *final_queue = new QLinkedList<const GEOSGeometry*>; const GEOSGeometry *geom; queue->append( the_geom ); int nGeom; int i; while ( !queue->isEmpty() ) { geom = queue->takeFirst(); GEOSContextHandle_t geosctxt = geosContext(); switch ( GEOSGeomTypeId_r( geosctxt, geom ) ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: nGeom = GEOSGetNumGeometries_r( geosctxt, geom ); for ( i = 0; i < nGeom; i++ ) { queue->append( GEOSGetGeometryN_r( geosctxt, geom, i ) ); } break; case GEOS_POINT: case GEOS_LINESTRING: case GEOS_POLYGON: final_queue->append( geom ); break; default: delete final_queue; delete queue; return NULL; } } delete queue; return final_queue; }
void Layer::joinConnectedFeatures() { // go through all label texts int connectedFeaturesId = 0; Q_FOREACH ( const QString& labelText, mConnectedTexts ) { if ( !mConnectedHashtable.contains( labelText ) ) continue; // shouldn't happen connectedFeaturesId++; QLinkedList<FeaturePart*>* parts = mConnectedHashtable.value( labelText ); // go one-by-one part, try to merge while ( !parts->isEmpty() && parts->count() > 1 ) { // part we'll be checking against other in this round FeaturePart* partCheck = parts->takeFirst(); FeaturePart* otherPart = _findConnectedPart( partCheck, parts ); if ( otherPart ) { // remove partCheck from r-tree double checkpartBMin[2], checkpartBMax[2]; partCheck->getBoundingBox( checkpartBMin, checkpartBMax ); double otherPartBMin[2], otherPartBMax[2]; otherPart->getBoundingBox( otherPartBMin, otherPartBMax ); // merge points from partCheck to p->item if ( otherPart->mergeWithFeaturePart( partCheck ) ) { // remove the parts we are joining from the index mFeatureIndex->Remove( checkpartBMin, checkpartBMax, partCheck ); mFeatureIndex->Remove( otherPartBMin, otherPartBMax, otherPart ); // reinsert merged line to r-tree (probably not needed) otherPart->getBoundingBox( otherPartBMin, otherPartBMax ); mFeatureIndex->Insert( otherPartBMin, otherPartBMax, otherPart ); mConnectedFeaturesIds.insert( partCheck->featureId(), connectedFeaturesId ); mConnectedFeaturesIds.insert( otherPart->featureId(), connectedFeaturesId ); mFeatureParts.removeOne( partCheck ); delete partCheck; } } } // we're done processing feature parts with this particular label text delete parts; mConnectedHashtable.remove( labelText ); } // we're done processing connected features //should be empty, but clear to be safe qDeleteAll( mConnectedHashtable ); mConnectedHashtable.clear(); mConnectedTexts.clear(); }
TEST_F(CoverArtUtilTest, searchImage) { // creating a temp track directory QString trackdir(QDir::tempPath() % "/TrackDir"); ASSERT_FALSE(QDir().exists(trackdir)); // it must start empty ASSERT_TRUE(QDir().mkpath(trackdir)); TrackPointer pTrack(Track::newTemporary(kTrackLocationTest)); SoundSourceProxy(pTrack).loadTrackMetadata(); QLinkedList<QFileInfo> covers; CoverArt res; // looking for cover in an empty directory res = CoverArtUtils::selectCoverArtForTrack(pTrack.data(), covers); CoverArt expected; expected.info.source = CoverInfo::GUESSED; EXPECT_EQ(expected, res); // Looking for a track with embedded cover. pTrack = TrackPointer(Track::newTemporary(kTrackLocationTest)); SoundSourceProxy(pTrack).loadTrackMetadataAndCoverArt(); expected = CoverArt(); expected.image = pTrack->getCoverArt().image; expected.info.type = CoverInfo::METADATA; expected.info.source = CoverInfo::GUESSED; expected.info.coverLocation = QString(); expected.info.hash = CoverArtUtils::calculateHash(expected.image); EXPECT_EQ(expected, pTrack->getCoverArt()); const char* format("jpg"); const QString qFormat(format); // Since we already parsed this image from the matadata in // kTrackLocationTest, hang on to it since we use it as a template for // stuff below. const QImage img = expected.image; QString trackBaseName = "cover-test"; QString trackAlbum = "album_name"; // Search Strategy // 0. If we have just one file, we will get it. // 1. %track-file-base%.jpg in the track directory for %track-file-base%.mp3 // 2. %album%.jpg // 3. cover.jpg // 4. front.jpg // 5. album.jpg // 6. folder.jpg // 7. if just one file exists take that otherwise none. // All the following expect the same image/hash to be selected. expected.image = img; expected.info.hash = CoverArtUtils::calculateHash(expected.image); // All the following expect FILE and GUESSED. expected.info.type = CoverInfo::FILE; expected.info.source = CoverInfo::GUESSED; // 0. saving just one cover in our temp track dir QString cLoc_foo = QString(trackdir % "/" % "foo." % qFormat); EXPECT_TRUE(img.save(cLoc_foo, format)); // looking for cover in an directory with one image will select that one. expected.image = QImage(cLoc_foo); expected.info.coverLocation = "foo.jpg"; expected.info.hash = CoverArtUtils::calculateHash(expected.image); covers << QFileInfo(cLoc_foo); res = CoverArtUtils::selectCoverArtForTrack(trackBaseName, trackAlbum, covers); EXPECT_EQ(expected, res); QFile::remove(cLoc_foo); QStringList extraCovers; // adding some extra images (bigger) just to populate the track dir. QString cLoc_big1 = QString(trackdir % "/" % "big1." % qFormat); EXPECT_TRUE(img.scaled(1000,1000).save(cLoc_big1, format)); extraCovers << cLoc_big1; QString cLoc_big2 = QString(trackdir % "/" % "big2." % qFormat); EXPECT_TRUE(img.scaled(900,900).save(cLoc_big2, format)); extraCovers << cLoc_big2; QString cLoc_big3 = QString(trackdir % "/" % "big3." % qFormat); EXPECT_TRUE(img.scaled(800,800).save(cLoc_big3, format)); extraCovers << cLoc_big3; // saving more covers using the preferred names in the right order QLinkedList<QFileInfo> prefCovers; // 1. track_filename.jpg QString cLoc_filename = QString(trackdir % "/cover-test." % qFormat); EXPECT_TRUE(img.scaled(500,500).save(cLoc_filename, format)); prefCovers << QFileInfo(cLoc_filename); // 2. album_name.jpg QString cLoc_albumName = QString(trackdir % "/album_name." % qFormat); EXPECT_TRUE(img.scaled(500,500).save(cLoc_albumName, format)); prefCovers << QFileInfo(cLoc_albumName); // 3. cover.jpg QString cLoc_cover = QString(trackdir % "/" % "cover." % qFormat); EXPECT_TRUE(img.scaled(400,400).save(cLoc_cover, format)); prefCovers << QFileInfo(cLoc_cover); // 4. front.jpg QString cLoc_front = QString(trackdir % "/" % "front." % qFormat); EXPECT_TRUE(img.scaled(300,300).save(cLoc_front, format)); prefCovers << QFileInfo(cLoc_front); // 5. album.jpg QString cLoc_album = QString(trackdir % "/" % "album." % qFormat); EXPECT_TRUE(img.scaled(100,100).save(cLoc_album, format)); prefCovers << QFileInfo(cLoc_album); // 6. folder.jpg QString cLoc_folder = QString(trackdir % "/" % "folder." % qFormat); EXPECT_TRUE(img.scaled(100,100).save(cLoc_folder, format)); prefCovers << QFileInfo(cLoc_folder); // 8. other1.jpg QString cLoc_other1 = QString(trackdir % "/" % "other1." % qFormat); EXPECT_TRUE(img.scaled(10,10).save(cLoc_other1, format)); prefCovers << QFileInfo(cLoc_other1); // 7. other2.jpg QString cLoc_other2 = QString(trackdir % "/" % "other2." % qFormat); EXPECT_TRUE(img.scaled(10,10).save(cLoc_other2, format)); prefCovers << QFileInfo(cLoc_other2); // we must find covers in the right order EXPECT_EQ(8, prefCovers.size()); // Remove the covers one by one from the front, checking that each one is // selected as we remove the previously-most-preferable cover. while (!prefCovers.isEmpty()) { QFileInfo cover = prefCovers.first(); // We expect no cover selected for other1 since there are 2 covers, // neither of which match our preferred cover names. other2 will be // selected once we get to it since it is the only cover available. if (cover.baseName() == "other1") { expected.image = QImage(); expected.info.type = CoverInfo::NONE; expected.info.coverLocation = QString(); expected.info.hash = 0; } else { expected.image = QImage(cover.filePath()); expected.info.type = CoverInfo::FILE; expected.info.coverLocation = cover.fileName(); expected.info.hash = CoverArtUtils::calculateHash(expected.image); } res = CoverArtUtils::selectCoverArtForTrack(trackBaseName, trackAlbum, prefCovers); EXPECT_QSTRING_EQ(expected.info.coverLocation, res.info.coverLocation); EXPECT_QSTRING_EQ(expected.info.hash, res.info.hash); EXPECT_EQ(expected, res); QFile::remove(cover.filePath()); prefCovers.pop_front(); } // // Additional tests // // what is chosen when cover.jpg and cover.JPG exists? // (it must always prefer the lighter cover) QString cLoc_coverJPG = trackdir % "/" % "cover." % "JPG"; EXPECT_TRUE(img.scaled(200,200).save(cLoc_coverJPG, "JPG")); prefCovers.append(QFileInfo(cLoc_coverJPG)); QString cLoc_coverjpg = trackdir % "/" % "cover." % "jpg"; EXPECT_TRUE(img.scaled(400,400).save(cLoc_coverjpg, "jpg")); prefCovers.append(QFileInfo(cLoc_coverjpg)); extraCovers << cLoc_coverJPG << cLoc_coverjpg; res = CoverArtUtils::selectCoverArtForTrack(trackBaseName, trackAlbum, prefCovers); expected.image = QImage(cLoc_coverJPG); expected.info.hash = CoverArtUtils::calculateHash(expected.image); expected.info.coverLocation = "cover.JPG"; EXPECT_EQ(expected, res); // As we are looking for %album%.jpg and %base_track.jpg%, // we need to check if everything works with UTF8 chars. trackBaseName = QString::fromUtf8("track_ðÑöæäî"); trackAlbum = QString::fromUtf8("öæäîðÑ_album"); prefCovers.clear(); // 2. album_name.jpg cLoc_albumName = QString(trackdir % "/" % trackAlbum % "." % qFormat); EXPECT_TRUE(img.save(cLoc_albumName, format)); prefCovers.append(QFileInfo(cLoc_albumName)); res = CoverArtUtils::selectCoverArtForTrack(trackBaseName, trackAlbum, prefCovers); expected.image = QImage(cLoc_albumName); expected.info.hash = CoverArtUtils::calculateHash(expected.image); expected.info.coverLocation = trackAlbum % ".jpg"; EXPECT_EQ(expected, res); // 1. track_filename.jpg cLoc_filename = QString(trackdir % "/" % trackBaseName % "." % qFormat); EXPECT_TRUE(img.save(cLoc_filename, format)); prefCovers.append(QFileInfo(cLoc_filename)); res = CoverArtUtils::selectCoverArtForTrack(trackBaseName, trackAlbum, prefCovers); expected.image = QImage(cLoc_filename); expected.info.hash = CoverArtUtils::calculateHash(expected.image); expected.info.coverLocation = trackBaseName % ".jpg"; EXPECT_EQ(expected, res); QFile::remove(cLoc_filename); QFile::remove(cLoc_albumName); // cleaning temp dir foreach (QString loc, extraCovers) { QFile::remove(loc); }
bool KNMusicPlaylistiTunesXMLParser::write(KNMusicPlaylistModel *playlist, const QString &filePath) { //Generate the plist document. QDomDocument plistDocument; //Initial the plist element. QDomElement plistRoot=plistDocument.createElement("plist"); plistRoot.setAttribute("version", "1.0"); plistDocument.appendChild(plistRoot); //Initial the dict element. QDomElement dictElement=plistDocument.createElement("dict"); plistRoot.appendChild(dictElement); appendDictValue(plistDocument, dictElement, "Major Version", 1); appendDictValue(plistDocument, dictElement, "Minor Version", 1); appendDictValue(plistDocument, dictElement, "Date", QDateTime::currentDateTime()); appendDictValue(plistDocument, dictElement, "Features", 5); appendDictValue(plistDocument, dictElement, "Show Content Ratings", true); //Generate database and song index list. QHash<QString, int> filePathIndex; QLinkedList<int> playlistIndexList; //Add paths to hash keys. for(int i=0; i<playlist->rowCount(); i++) { //Get current path. QString currentPath=playlist->rowProperty(i, FilePathRole).toString(); //Check the path in the index hash. int currentIndex=filePathIndex.value(currentPath, -1); //If we never insert this path to the index, if(currentIndex==-1) { //Get the new index. currentIndex=i; //Insert the path to the hash. filePathIndex.insert(currentPath, currentIndex); } //Append the list. playlistIndexList.append(currentIndex); } //Output the database info to dict. //Initial the elements. QDomElement tracksKey=plistDocument.createElement("key"), tracksDict=plistDocument.createElement("dict"); QDomText tracksKeyValue=plistDocument.createTextNode("Tracks"); tracksKey.appendChild(tracksKeyValue); //Add to dict elements. dictElement.appendChild(tracksKey); dictElement.appendChild(tracksDict); //Write database info. QList<int> songIndexList=filePathIndex.values(); while(!songIndexList.isEmpty()) { int currentRow=songIndexList.takeFirst(), trackID=currentRow+100; //Generate current row key and dict. QDomElement trackKey=plistDocument.createElement("key"), trackDict=plistDocument.createElement("dict"); //Generate the track key value. QDomText trackKeyValue= plistDocument.createTextNode(QString::number(trackID)); trackKey.appendChild(trackKeyValue); //Get the detail info. const KNMusicDetailInfo detailInfo=playlist->rowDetailInfo(currentRow); //Generate the dict. appendDictValue(plistDocument, trackDict, "Track ID", trackID); appendDictValue(plistDocument, trackDict, "Name", detailInfo.textLists[Name]); appendDictValue(plistDocument, trackDict, "Artist", detailInfo.textLists[Artist]); appendDictValue(plistDocument, trackDict, "Album Artist", detailInfo.textLists[AlbumArtist]); appendDictValue(plistDocument, trackDict, "Genre", detailInfo.textLists[Genre]); appendDictValue(plistDocument, trackDict, "Kind", detailInfo.textLists[Kind]); appendDictValue(plistDocument, trackDict, "Size", detailInfo.size); appendDictValue(plistDocument, trackDict, "Total Time", detailInfo.duration); appendDictValue(plistDocument, trackDict, "Track Number", detailInfo.textLists[TrackNumber].toString().toInt()); appendDictValue(plistDocument, trackDict, "Track Count", detailInfo.textLists[TrackCount].toString().toInt()); appendDictValue(plistDocument, trackDict, "Year", detailInfo.textLists[Year].toString().toInt()); appendDictValue(plistDocument, trackDict, "Date Modified", detailInfo.dateModified); appendDictValue(plistDocument, trackDict, "Date Added", detailInfo.dateAdded); appendDictValue(plistDocument, trackDict, "Bit Rate", detailInfo.bitRate); appendDictValue(plistDocument, trackDict, "Sample Rate", detailInfo.samplingRate); appendDictValue(plistDocument, trackDict, "Track Type", "File"); QString fileLocate=QUrl::fromLocalFile(detailInfo.filePath).toString(); #ifdef Q_OS_WIN fileLocate.insert(7, "localhost"); #endif appendDictValue(plistDocument, trackDict, "Location", QString(QUrl::toPercentEncoding(fileLocate, "/:"))); appendDictValue(plistDocument, trackDict, "File Folder Count", -1); appendDictValue(plistDocument, trackDict, "Library Folder Count", -1); //Add the key and dict to track. tracksDict.appendChild(trackKey); tracksDict.appendChild(trackDict); } //Output the playlist info to dict. QDomElement playlistKey=plistDocument.createElement("key"), playlistArray=plistDocument.createElement("array"); QDomText playlistKeyValue=plistDocument.createTextNode("Playlists"); playlistKey.appendChild(playlistKeyValue); //Add the key and array to dict element. dictElement.appendChild(playlistKey); dictElement.appendChild(playlistArray); //Generate current playlist information. QDomElement playlistDict=plistDocument.createElement("dict"); playlistArray.appendChild(playlistDict); //Set playlist information to the dict. appendDictValue(plistDocument, playlistDict, "Name", playlist->title()); appendDictValue(plistDocument, playlistDict, "Playlist ID", "99"); appendDictValue(plistDocument, playlistDict, "All Items", true); //Generate playlist items array. QDomElement playlistItemsKey=plistDocument.createElement("key"), playlistItemsArray=plistDocument.createElement("array"); QDomText playlistItemsKeyValue= plistDocument.createTextNode("Playlist Items"); playlistItemsKey.appendChild(playlistItemsKeyValue); //Add to current playlist dict. playlistDict.appendChild(playlistItemsKey); playlistDict.appendChild(playlistItemsArray); //Generate Track ID dicts. while(!playlistIndexList.isEmpty()) { QDomElement currentTrackDict=plistDocument.createElement("dict"); appendDictValue(plistDocument, currentTrackDict, "Track ID", 100+playlistIndexList.takeFirst()); //Add the dict to the array. playlistItemsArray.appendChild(currentTrackDict); } return writeContent(filePath, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE " "plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"" " \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + plistDocument.toString(4)); }
void PointSet::splitPolygons( QLinkedList<PointSet *> &shapes_toProcess, QLinkedList<PointSet *> &shapes_final, double xrm, double yrm ) { int i, j; int nbp; double *x = nullptr; double *y = nullptr; int *pts = nullptr; int *cHull = nullptr; int cHullSize; double cp; double bestcp = 0; double bestArea = 0; double area; double base; double b, c; double s; int ihs; int ihn; int ips; int ipn; int holeS = -1; // hole start and end points int holeE = -1; int retainedPt = -1; int pt = 0; double labelArea = xrm * yrm; PointSet *shape = nullptr; while ( !shapes_toProcess.isEmpty() ) { shape = shapes_toProcess.takeFirst(); x = shape->x; y = shape->y; nbp = shape->nbPoints; pts = new int[nbp]; for ( i = 0; i < nbp; i++ ) { pts[i] = i; } // conpute convex hull shape->cHullSize = GeomFunction::convexHullId( pts, x, y, nbp, shape->cHull ); cHull = shape->cHull; cHullSize = shape->cHullSize; bestArea = 0; retainedPt = -1; // lookup for a hole for ( ihs = 0; ihs < cHullSize; ihs++ ) { // ihs->ihn => cHull'seg ihn = ( ihs + 1 ) % cHullSize; ips = cHull[ihs]; ipn = ( ips + 1 ) % nbp; if ( ipn != cHull[ihn] ) // next point on shape is not the next point on cHull => there is a hole here ! { bestcp = 0; pt = -1; // lookup for the deepest point in the hole for ( i = ips; i != cHull[ihn]; i = ( i + 1 ) % nbp ) { cp = std::fabs( GeomFunction::cross_product( x[cHull[ihs]], y[cHull[ihs]], x[cHull[ihn]], y[cHull[ihn]], x[i], y[i] ) ); if ( cp - bestcp > EPSILON ) { bestcp = cp; pt = i; } } if ( pt != -1 ) { // compute the ihs->ihn->pt triangle's area base = GeomFunction::dist_euc2d( x[cHull[ihs]], y[cHull[ihs]], x[cHull[ihn]], y[cHull[ihn]] ); b = GeomFunction::dist_euc2d( x[cHull[ihs]], y[cHull[ihs]], x[pt], y[pt] ); c = GeomFunction::dist_euc2d( x[cHull[ihn]], y[cHull[ihn]], x[pt], y[pt] ); s = ( base + b + c ) / 2; // s = half perimeter area = s * ( s - base ) * ( s - b ) * ( s - c ); if ( area < 0 ) area = -area; // retain the biggest area if ( area - bestArea > EPSILON ) { bestArea = area; retainedPt = pt; holeS = ihs; holeE = ihn; } } } } // we have a hole, its area, and the deppest point in hole // we're going to find the second point to cup the shape // holeS = hole starting point // holeE = hole ending point // retainedPt = deppest point in hole // bestArea = area of triangle HoleS->holeE->retainedPoint bestArea = std::sqrt( bestArea ); double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx = 0, pty = 0, fptx = 0, fpty = 0; int ps = -1, pe = -1, fps = -1, fpe = -1; if ( retainedPt >= 0 && bestArea > labelArea ) // there is a hole so we'll cut the shape in two new shape (only if hole area is bigger than twice labelArea) { c = std::numeric_limits<double>::max(); // iterate on all shape points except points which are in the hole bool isValid; int k, l; for ( i = ( cHull[holeE] + 1 ) % nbp; i != ( cHull[holeS] - 1 + nbp ) % nbp; i = j ) { j = ( i + 1 ) % nbp; // i->j is shape segment not in hole // compute distance between retainedPoint and segment // whether perpendicular distance (if retaindPoint is fronting segment i->j) // or distance between retainedPt and i or j (choose the nearest) seg_length = GeomFunction::dist_euc2d( x[i], y[i], x[j], y[j] ); cx = ( x[i] + x[j] ) / 2.0; cy = ( y[i] + y[j] ) / 2.0; dx = cy - y[i]; dy = cx - x[i]; ex = cx - dx; ey = cy + dy; fx = cx + dx; fy = cy - dy; if ( seg_length < EPSILON || std::fabs( ( b = GeomFunction::cross_product( ex, ey, fx, fy, x[retainedPt], y[retainedPt] ) / ( seg_length ) ) ) > ( seg_length / 2 ) ) // retainedPt is not fronting i->j { if ( ( ex = GeomFunction::dist_euc2d_sq( x[i], y[i], x[retainedPt], y[retainedPt] ) ) < ( ey = GeomFunction::dist_euc2d_sq( x[j], y[j], x[retainedPt], y[retainedPt] ) ) ) { b = ex; ps = i; pe = i; } else { b = ey; ps = j; pe = j; } } else // point fronting i->j => compute pependicular distance => create a new point { b = GeomFunction::cross_product( x[i], y[i], x[j], y[j], x[retainedPt], y[retainedPt] ) / seg_length; b *= b; ps = i; pe = j; if ( !GeomFunction::computeLineIntersection( x[i], y[i], x[j], y[j], x[retainedPt], y[retainedPt], x[retainedPt] - dx, y[retainedPt] + dy, &ptx, &pty ) ) { //error - it should intersect the line } } isValid = true; double pointX, pointY; if ( ps == pe ) { pointX = x[pe]; pointY = y[pe]; } else { pointX = ptx; pointY = pty; } for ( k = cHull[holeS]; k != cHull[holeE]; k = ( k + 1 ) % nbp ) { l = ( k + 1 ) % nbp; if ( GeomFunction::isSegIntersects( x[retainedPt], y[retainedPt], pointX, pointY, x[k], y[k], x[l], y[l] ) ) { isValid = false; break; } } if ( isValid && b < c ) { c = b; fps = ps; fpe = pe; fptx = ptx; fpty = pty; } } // for point which are not in hole // we will cut the shapeu in two new shapes, one from [retainedPoint] to [newPoint] and one form [newPoint] to [retainedPoint] int imin = retainedPt; int imax = ( ( ( fps < retainedPt && fpe < retainedPt ) || ( fps > retainedPt && fpe > retainedPt ) ) ? std::min( fps, fpe ) : std::max( fps, fpe ) ); int nbPtSh1, nbPtSh2; // how many points in new shapes ? if ( imax > imin ) nbPtSh1 = imax - imin + 1 + ( fpe != fps ); else nbPtSh1 = imax + nbp - imin + 1 + ( fpe != fps ); if ( ( imax == fps ? fpe : fps ) < imin ) nbPtSh2 = imin - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps ); else nbPtSh2 = imin + nbp - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps ); if ( retainedPt == -1 || fps == -1 || fpe == -1 ) { if ( shape->parent ) delete shape; } // check for useless spliting else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp ) { shapes_final.append( shape ); } else { PointSet *newShape = shape->extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ); if ( shape->parent ) newShape->parent = shape->parent; else newShape->parent = shape; shapes_toProcess.append( newShape ); if ( imax == fps ) imax = fpe; else imax = fps; newShape = shape->extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ); if ( shape->parent ) newShape->parent = shape->parent; else newShape->parent = shape; shapes_toProcess.append( newShape ); if ( shape->parent ) delete shape; } } else { shapes_final.append( shape ); } delete[] pts; } }
/** * Produces FLASH erase and write plans for optimally programming application code into * a device. * * This routine assumes that pages filled with blank or "NOP" instructions (0xFFFF) do * not need to be erased nor written. For most applications, this will be sufficient, * providing extremely fast programming. * * To guarantee clean memory, perform a Verify After Write CRC check on each Erase * Block. This will find any leftover junk data from older firmware that can be erased. */ void DeviceWritePlanner::planFlashWrite(QLinkedList<Device::MemoryRange>& eraseList, QLinkedList<Device::MemoryRange>& writeList, unsigned int start, unsigned int end, unsigned int* data, unsigned int* existingData) { unsigned int address = start; Device::MemoryRange block; while(address < end) { address = skipEmptyFlashPages(address, data); block.start = address; if(address >= end) { break; } address = findEndFlashWrite(address, data); if(address >= end) { address = end; } block.end = address; if(device->family == Device::PIC16 && !device->hasEraseFlashCommand()) { // Certain PIC16 devices (such as PIC16F882) have a peculiar automatic erase // during write feature. To make that work, writes must be expanded to align // with Erase Block boundaries. block.start -= (block.start % device->eraseBlockSizeFLASH); if(block.end % device->eraseBlockSizeFLASH) { block.end += device->eraseBlockSizeFLASH - (block.end % device->eraseBlockSizeFLASH); address = block.end; } } writeList.append(block); address++; } if(existingData == NULL && device->family == Device::PIC32) { // Because PIC32 has Bulk Erase available for bootloader use, // it's faster to simply erase the entire FLASH memory space // than erasing specific erase blocks using an erase plan. block.start = device->startFLASH; block.end = device->endFLASH; eraseList.append(block); } else { if(existingData != NULL) { QLinkedList<Device::MemoryRange>::iterator it; for(it = writeList.begin(); it != writeList.end(); ++it) { qDebug("unpruned write(%X to %X)", it->start, it->end); } doNotWriteExistingData(writeList, start, end, data, existingData); for(it = writeList.begin(); it != writeList.end(); ++it) { qDebug("pruned write(%X to %X)", it->start, it->end); } } if(!writeList.isEmpty()) { if(device->hasEraseFlashCommand()) { flashEraseList(eraseList, writeList, data, existingData); } EraseAppCheckFirst(eraseList); WriteAppCheckLast(writeList); if(writeConfig) { eraseConfigPageLast(eraseList); writeConfigPageFirst(writeList); doNotEraseBootBlock(eraseList); // needed in case boot block resides on config page } else { doNotEraseConfigPage(eraseList); } doNotEraseInterruptVectorTable(eraseList); } } packetSizeWriteList(writeList); }
bool KNMusicLRCLyricsParser::parseData(const QString &lyricsTextData, QList<qint64> &positionList, QStringList &textList) { //Clear the position list and text list. positionList.clear(); textList.clear(); //Split the lyrics text data. QStringList lyricsRawData=lyricsTextData.split(QRegExp("\n"), QString::SkipEmptyParts); QList<LyricsLine> lyricsLineList; //Remove the same line in the lyrics raw data. lyricsRawData.removeDuplicates(); //Parse the lyrics raw data. while(!lyricsRawData.isEmpty()) { //Get the first line of the current list and remove all spaces. QString currentLine=lyricsRawData.takeFirst().simplified(); //Find frames in the current line. QRegularExpressionMatchIterator frameMatcher= m_frameCatchRegExp.globalMatch(currentLine); int lastPosition=0; QLinkedList<QString> frameLists; //Get all the frames. while(frameMatcher.hasNext()) { QRegularExpressionMatch matchedFrame=frameMatcher.next(); //Check is the current matched frame is at the last position. //An example is: // [00:00:01] Won't chu kiss me![00:00:03]Saikou no if(matchedFrame.capturedStart()!=lastPosition) { //Then we should pick out the data before the current start and //last position. //Like 'Won't chu kiss me!' in the example. QString text=currentLine.mid(lastPosition, matchedFrame.capturedStart()-lastPosition); //Parse the datas to frame lists. while(!frameLists.isEmpty()) { parseFrames(frameLists.takeFirst(), text, lyricsLineList); } } //Add current frame to frame list. frameLists.append(currentLine.mid(matchedFrame.capturedStart(), matchedFrame.capturedLength())); //Update the last position. lastPosition=matchedFrame.capturedEnd(); } //Remove the previous datas, and parse the left datas to frame lists. currentLine.remove(0, lastPosition); while(!frameLists.isEmpty()) { parseFrames(frameLists.takeFirst(), currentLine, lyricsLineList); } } //Check is the lyrics line list is empty or not, if it's empty, means we //can't parse it. if(lyricsLineList.isEmpty()) { return false; } //Sorr the lyrics line. //- Why stable sort? // Because there might be some frames at the same time. Display them with //their exist order. qStableSort(lyricsLineList.begin(), lyricsLineList.end(), frameLessThan); //Combine the same timestamp lyrics. QMap<qint64, QString> lyricsCombineMap; for(QList<LyricsLine>::iterator i=lyricsLineList.begin(); i!=lyricsLineList.end(); ++i) { lyricsCombineMap.insert((*i).position, lyricsCombineMap.contains((*i).position)? lyricsCombineMap.value((*i).position)+'\n'+(*i).text: (*i).text); } //Export the position and the text. positionList=lyricsCombineMap.keys(); textList=lyricsCombineMap.values(); return true; }
bool KNMusicTagWav::parseTag(QFile &musicFile, QDataStream &musicDataStream, KNMusicAnalysisItem &analysisItem) { //Check file size. if(musicFile.size()<12) { //It cannot be a wav format file, until a valid one. return false; } //Gernerate the header cache. char rawHeader[12]; //Read the header. musicDataStream.readRawData(rawHeader, 12); //Check the riff header and the wave header. if(memcmp(rawHeader, m_riffHeader, 4)!=0 || memcmp(rawHeader+8, m_waveHeader, 4)!=0) { //This is not a wav file. return false; } /* * WAV file is a combination of several chunks. * Read all the chunks, and find LIST and id32 chunk. */ //Get the music file size. qint64 fileSize=musicFile.size(); //Generate the chunk header cache. char chunkHeader[8]; //Initial the chunk found flag. bool listFound=false, id32Found=false; //We have to prepare the list here and write the data after parse all the //data, we want the id32 chunk has a higher priority than list chunk. //Prepare the wav item list for list chunk. QList<WAVItem> listData; //Generate the raw frame linked list for id32 chunk. QLinkedList<ID3v2Frame> frames; //Generate the id3v2 frame function set for id32 chunk. ID3v2FunctionSet functionSet; //Start finding the chunk. while(musicDataStream.device()->pos()<fileSize && !listFound && !id32Found) { //Read chunk head. musicDataStream.readRawData(chunkHeader, 8); //Calculate the chunk size. quint32 chunkSize=KNMusicUtil::inverseCharToInt32(chunkHeader+4); //Check if it's list chunk if(memcmp(chunkHeader, m_listChunk, 4)==0) { //Set list chunk found flag to true. listFound=true; //Generate chunk size cache. char *listRawData=new char[chunkSize]; //Read the raw data. musicDataStream.readRawData(listRawData, chunkSize); //Parse list chunk. parseListChunk(listRawData, chunkSize, listData); //Recover memory. delete[] listRawData; } //Check if it's id32 chunk. else if(memcmp(chunkHeader, m_id32Chunk, 4)==0) { //Generate ID3v2 header cache. char rawHeader[10]; //Generate ID3v2 header structure. ID3v2Header header; //Read ID3v2 header data. musicDataStream.readRawData(rawHeader, 10); //Parse the ID3v2 header. //and then Check is chunk size smaller than tag size. if(!parseID3v2Header(rawHeader, header) || chunkSize<(header.size+10)) { //If we cannot parse it, skip the whole chunk. musicDataStream.skipRawData(chunkSize-10); //Continue to next chunk. continue; } //Generate the raw tag data field. char *rawTagData=new char[header.size]; //Read the raw tag data. musicDataStream.readRawData(rawTagData, header.size); //Get the function set according to the minor version of the header. getId3v2FunctionSet(header.major, functionSet); //Parse the raw data. parseID3v2RawData(rawTagData, header, functionSet, frames); //Recover the memory. delete[] rawTagData; //Set the id32 chunk find flag to true. id32Found=true; } //For all the other chunks. else { //Skip the data. musicDataStream.skipRawData(chunkSize); } } //Check if the list data is not empty, first. //The data can be overwrite by id32 chunk data. if(!listData.isEmpty()) { //Check all the data in the wav item list. for(auto i : listData) { //Get the index of current item. int chunkIndex=m_listKeyIndex.value(i.key, -1); //Check the validation of chunk index. if(chunkIndex==-1) { //Abandon the current index. continue; } //Set the data. analysisItem.detailInfo.textLists[chunkIndex]= QVariant(i.value); } } //Check id32 chunk data then. if(!frames.isEmpty()) { //Write the tag to analysis info. writeFrameToDetails(frames, functionSet, analysisItem); } //Mission complete. return true; }
//static CoverArt CoverArtUtils::selectCoverArtForTrack( const QString& trackBaseName, const QString& albumName, const QLinkedList<QFileInfo>& covers) { CoverArt art; art.info.source = CoverInfo::GUESSED; if (covers.isEmpty()) { return art; } PreferredCoverType bestType = NONE; const QFileInfo* bestInfo = NULL; // If there is a single image then we use it unconditionally. Otherwise // we use the priority order described in PreferredCoverType. Notably, // if there are multiple image files in the folder we require they match // one of the name patterns -- otherwise we run the risk of picking an // arbitrary image that happens to be in the same folder as some of the // user's music files. if (covers.size() == 1) { bestInfo = &covers.first(); } else { // TODO(XXX) Sort instead so that we can fall-back if one fails to // open? foreach (const QFileInfo& file, covers) { const QString coverBaseName = file.baseName(); if (bestType > TRACK_BASENAME && coverBaseName.compare(trackBaseName, Qt::CaseInsensitive) == 0) { bestType = TRACK_BASENAME; bestInfo = &file; // This is the best type so we know we're done. break; } else if (bestType > ALBUM_NAME && coverBaseName.compare(albumName, Qt::CaseInsensitive) == 0) { bestType = ALBUM_NAME; bestInfo = &file; } else if (bestType > COVER && coverBaseName.compare(QLatin1String("cover"), Qt::CaseInsensitive) == 0) { bestType = COVER; bestInfo = &file; } else if (bestType > FRONT && coverBaseName.compare(QLatin1String("front"), Qt::CaseInsensitive) == 0) { bestType = FRONT; bestInfo = &file; } else if (bestType > ALBUM && coverBaseName.compare(QLatin1String("album"), Qt::CaseInsensitive) == 0) { bestType = ALBUM; bestInfo = &file; } else if (bestType > FOLDER && coverBaseName.compare(QLatin1String("folder"), Qt::CaseInsensitive) == 0) { bestType = FOLDER; bestInfo = &file; } } } if (bestInfo != NULL) { art.image = QImage(bestInfo->filePath()); if (!art.image.isNull()) { art.info.source = CoverInfo::GUESSED; art.info.type = CoverInfo::FILE; // TODO() here we may introduce a duplicate hash code art.info.hash = CoverArtUtils::calculateHash(art.image); art.info.coverLocation = bestInfo->fileName(); return art; } } return art; }
bool Layer::registerFeature( QgsLabelFeature* lf ) { if ( lf->size().width() < 0 || lf->size().height() < 0 ) return false; mMutex.lock(); if ( mHashtable.contains( lf->id() ) ) { mMutex.unlock(); //A feature with this id already exists. Don't throw an exception as sometimes, //the same feature is added twice (dateline split with otf-reprojection) return false; } // assign label feature to this PAL layer lf->setLayer( this ); // Split MULTI GEOM and Collection in simple geometries bool addedFeature = false; double geom_size = -1, biggest_size = -1; FeaturePart* biggest_part = nullptr; // break the (possibly multi-part) geometry into simple geometries QLinkedList<const GEOSGeometry*>* simpleGeometries = Util::unmulti( lf->geometry() ); if ( !simpleGeometries ) // unmulti() failed? { mMutex.unlock(); throw InternalException::UnknownGeometry(); } GEOSContextHandle_t geosctxt = geosContext(); bool featureGeomIsObstacleGeom = !lf->obstacleGeometry(); while ( !simpleGeometries->isEmpty() ) { const GEOSGeometry* geom = simpleGeometries->takeFirst(); // ignore invalid geometries (e.g. polygons with self-intersecting rings) if ( GEOSisValid_r( geosctxt, geom ) != 1 ) // 0=invalid, 1=valid, 2=exception { continue; } int type = GEOSGeomTypeId_r( geosctxt, geom ); if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON ) { mMutex.unlock(); throw InternalException::UnknownGeometry(); } FeaturePart* fpart = new FeaturePart( lf, geom ); // ignore invalid geometries if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) || ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) ) { delete fpart; continue; } // polygons: reorder coordinates if ( type == GEOS_POLYGON && GeomFunction::reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 ) { delete fpart; continue; } // is the feature well defined? TODO Check epsilon bool labelWellDefined = ( lf->size().width() > 0.0000001 && lf->size().height() > 0.0000001 ); if ( lf->isObstacle() && featureGeomIsObstacleGeom ) { //if we are not labelling the layer, only insert it into the obstacle list and avoid an //unnecessary copy if ( mLabelLayer && labelWellDefined ) { addObstaclePart( new FeaturePart( *fpart ) ); } else { addObstaclePart( fpart ); fpart = nullptr; } } // feature has to be labeled? if ( !mLabelLayer || !labelWellDefined ) { //nothing more to do for this part delete fpart; continue; } if ( mMode == LabelPerFeature && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) ) { if ( type == GEOS_LINESTRING ) GEOSLength_r( geosctxt, geom, &geom_size ); else if ( type == GEOS_POLYGON ) GEOSArea_r( geosctxt, geom, &geom_size ); if ( geom_size > biggest_size ) { biggest_size = geom_size; delete biggest_part; // safe with NULL part biggest_part = fpart; } else { delete fpart; } continue; // don't add the feature part now, do it later } // feature part is ready! addFeaturePart( fpart, lf->labelText() ); addedFeature = true; } delete simpleGeometries; if ( !featureGeomIsObstacleGeom ) { //do the same for the obstacle geometry simpleGeometries = Util::unmulti( lf->obstacleGeometry() ); if ( !simpleGeometries ) // unmulti() failed? { mMutex.unlock(); throw InternalException::UnknownGeometry(); } while ( !simpleGeometries->isEmpty() ) { const GEOSGeometry* geom = simpleGeometries->takeFirst(); // ignore invalid geometries (e.g. polygons with self-intersecting rings) if ( GEOSisValid_r( geosctxt, geom ) != 1 ) // 0=invalid, 1=valid, 2=exception { continue; } int type = GEOSGeomTypeId_r( geosctxt, geom ); if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON ) { mMutex.unlock(); throw InternalException::UnknownGeometry(); } FeaturePart* fpart = new FeaturePart( lf, geom ); // ignore invalid geometries if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) || ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) ) { delete fpart; continue; } // polygons: reorder coordinates if ( type == GEOS_POLYGON && GeomFunction::reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 ) { delete fpart; continue; } // feature part is ready! addObstaclePart( fpart ); } delete simpleGeometries; } mMutex.unlock(); // if using only biggest parts... if (( mMode == LabelPerFeature || lf->hasFixedPosition() ) && biggest_part ) { addFeaturePart( biggest_part, lf->labelText() ); addedFeature = true; } // add feature to layer if we have added something if ( addedFeature ) { mHashtable.insert( lf->id(), lf ); } return addedFeature; // true if we've added something }
std::unique_ptr<Problem> Pal::extract( const QgsRectangle &extent, const QgsGeometry &mapBoundary ) { // to store obstacles RTree<FeaturePart *, double, 2, double> *obstacles = new RTree<FeaturePart *, double, 2, double>(); std::unique_ptr< Problem > prob = qgis::make_unique< Problem >(); int i, j; double bbx[4]; double bby[4]; double amin[2]; double amax[2]; int max_p = 0; LabelPosition *lp = nullptr; bbx[0] = bbx[3] = amin[0] = prob->bbox[0] = extent.xMinimum(); bby[0] = bby[1] = amin[1] = prob->bbox[1] = extent.yMinimum(); bbx[1] = bbx[2] = amax[0] = prob->bbox[2] = extent.xMaximum(); bby[2] = bby[3] = amax[1] = prob->bbox[3] = extent.yMaximum(); prob->pal = this; QLinkedList<Feats *> *fFeats = new QLinkedList<Feats *>; FeatCallBackCtx context; // prepare map boundary geos::unique_ptr mapBoundaryGeos( QgsGeos::asGeos( mapBoundary ) ); geos::prepared_unique_ptr mapBoundaryPrepared( GEOSPrepare_r( QgsGeos::getGEOSHandler(), mapBoundaryGeos.get() ) ); context.fFeats = fFeats; context.obstacles = obstacles; context.candidates = prob->candidates; context.mapBoundary = mapBoundaryPrepared.get(); ObstacleCallBackCtx obstacleContext; obstacleContext.obstacles = obstacles; obstacleContext.obstacleCount = 0; // first step : extract features from layers int previousFeatureCount = 0; int previousObstacleCount = 0; QStringList layersWithFeaturesInBBox; mMutex.lock(); const auto constMLayers = mLayers; for ( Layer *layer : constMLayers ) { if ( !layer ) { // invalid layer name continue; } // only select those who are active if ( !layer->active() ) continue; // check for connected features with the same label text and join them if ( layer->mergeConnectedLines() ) layer->joinConnectedFeatures(); layer->chopFeaturesAtRepeatDistance(); layer->mMutex.lock(); // find features within bounding box and generate candidates list context.layer = layer; layer->mFeatureIndex->Search( amin, amax, extractFeatCallback, static_cast< void * >( &context ) ); // find obstacles within bounding box layer->mObstacleIndex->Search( amin, amax, extractObstaclesCallback, static_cast< void * >( &obstacleContext ) ); layer->mMutex.unlock(); if ( context.fFeats->size() - previousFeatureCount > 0 || obstacleContext.obstacleCount > previousObstacleCount ) { layersWithFeaturesInBBox << layer->name(); } previousFeatureCount = context.fFeats->size(); previousObstacleCount = obstacleContext.obstacleCount; } mMutex.unlock(); prob->nbLabelledLayers = layersWithFeaturesInBBox.size(); prob->labelledLayersName = layersWithFeaturesInBBox; if ( fFeats->isEmpty() ) { delete fFeats; delete obstacles; return nullptr; } prob->nbft = fFeats->size(); prob->nblp = 0; prob->featNbLp = new int [prob->nbft]; prob->featStartId = new int [prob->nbft]; prob->inactiveCost = new double[prob->nbft]; Feats *feat = nullptr; // Filtering label positions against obstacles amin[0] = amin[1] = std::numeric_limits<double>::lowest(); amax[0] = amax[1] = std::numeric_limits<double>::max(); FilterContext filterCtx; filterCtx.cdtsIndex = prob->candidates; filterCtx.pal = this; obstacles->Search( amin, amax, filteringCallback, static_cast< void * >( &filterCtx ) ); if ( isCanceled() ) { const auto constFFeats = *fFeats; for ( Feats *feat : constFFeats ) { qDeleteAll( feat->lPos ); feat->lPos.clear(); } qDeleteAll( *fFeats ); delete fFeats; delete obstacles; return nullptr; } int idlp = 0; for ( i = 0; i < prob->nbft; i++ ) /* foreach feature into prob */ { feat = fFeats->takeFirst(); prob->featStartId[i] = idlp; prob->inactiveCost[i] = std::pow( 2, 10 - 10 * feat->priority ); switch ( feat->feature->getGeosType() ) { case GEOS_POINT: max_p = point_p; break; case GEOS_LINESTRING: max_p = line_p; break; case GEOS_POLYGON: max_p = poly_p; break; } // sort candidates by cost, skip less interesting ones, calculate polygon costs (if using polygons) max_p = CostCalculator::finalizeCandidatesCosts( feat, max_p, obstacles, bbx, bby ); // only keep the 'max_p' best candidates while ( feat->lPos.count() > max_p ) { // TODO remove from index feat->lPos.last()->removeFromIndex( prob->candidates ); delete feat->lPos.takeLast(); } // update problem's # candidate prob->featNbLp[i] = feat->lPos.count(); prob->nblp += feat->lPos.count(); // add all candidates into a rtree (to speed up conflicts searching) for ( j = 0; j < feat->lPos.count(); j++, idlp++ ) { lp = feat->lPos.at( j ); //lp->insertIntoIndex(prob->candidates); lp->setProblemIds( i, idlp ); // bugfix #1 (maxence 10/23/2008) } fFeats->append( feat ); } int nbOverlaps = 0; while ( !fFeats->isEmpty() ) // foreach feature { if ( isCanceled() ) { const auto constFFeats = *fFeats; for ( Feats *feat : constFFeats ) { qDeleteAll( feat->lPos ); feat->lPos.clear(); } qDeleteAll( *fFeats ); delete fFeats; delete obstacles; return nullptr; } feat = fFeats->takeFirst(); while ( !feat->lPos.isEmpty() ) // foreach label candidate { lp = feat->lPos.takeFirst(); lp->resetNumOverlaps(); // make sure that candidate's cost is less than 1 lp->validateCost(); prob->addCandidatePosition( lp ); //prob->feat[idlp] = j; lp->getBoundingBox( amin, amax ); // lookup for overlapping candidate prob->candidates->Search( amin, amax, LabelPosition::countOverlapCallback, static_cast< void * >( lp ) ); nbOverlaps += lp->getNumOverlaps(); } delete feat; } delete fFeats; //delete candidates; delete obstacles; nbOverlaps /= 2; prob->all_nblp = prob->nblp; prob->nbOverlap = nbOverlaps; return prob; }
void compile(QString path,QStringList& import,QFile &out){ QFile fp(path); if(fp.open(QFile::ReadOnly)){ QDir dir(QFileInfo(fp).absoluteDir()); QString modName = QFileInfo(fp).baseName(); if(readLine(fp).trimmed()!=FILE_HEAD){ qDebug("Indicated file is not a algorithm file of Uranus2"); exit(0); } int pIndent,cIndent=0,functionIndent=0; Function* function=0; QRegExp keyWord("(\\s*)(\\w+)\\s",Qt::CaseInsensitive); QRegExp argHook("(<.+>)?(.+)?"); QLinkedList<StackItem*> stack; while(!fp.atEnd()){ QString line=QString::fromUtf8(fp.readLine()); keyWord.indexIn(line); QString key=keyWord.cap(2).toLower(); line=line.mid(keyWord.cap().length()).trimmed(); pIndent = cIndent; cIndent=keyWord.cap(1).length(); if(cIndent<functionIndent){ if(function!=0){ function->write(out); function=0; } }else if(cIndent<=pIndent){ while(pIndent>=cIndent){ pIndent--; if(!stack.isEmpty()){ stack.pop_back(); } } } StackItem* parent = (stack.isEmpty())?0:stack.back(), *self=new StackItem(key,line,cIndent); stack.push_back(self); if(key=="import"){ import.append(dir.absoluteFilePath(line)); }else if(key=="function"){ function=new Function(modName,line); functionIndent=cIndent+1; }else if(key=="hint"){ if(function!=0){ if(parent->key=="function") self->indent++; self->outBegin="#"+line; function->append(self); } }else if(key=="arg"){ if(parent->key=="function"&&function){ function->args()<<line; } }else if(key=="assign"){ self->outBegin=line+"="; function->append(self); }else if(key=="value"){ if(parent->key=="assign"){ argHook.indexIn(line); if(argHook.cap(1)=="<list>"){ }else if(argHook.cap(1)=="<function>"){ }else if(argHook.cap(1)=="<variable>"){ self->outBegin=argHook.cap(2).trimmed(); }else{ self->outBegin=line.trimmed(); } parent->addChild(self); } }else if(key=="branch"){ self->outBegin="if True:"; function->append(self); }else if(key=="call"){ QString fname; if(line.left(3)=="://"){ fname=Function::conv(modName,line.mid(3)); }else{ QStringList f = line.split("/"); if(f.count()==2){ fname=Function::conv(f.at(0),f.at(1)); } } self->outBegin=fname+"("; self->outSep=","; self->outEnd=")"; if(parent->key=="do"){ function->append(self); }else{ parent->addChild(self); } }else if(key=="conditional"){ self->outBegin="if True:"; function->append(self); }else if(key=="do"){ }else if(key=="list"){ self->outBegin="["; self->outSep=","; self->outEnd="]"; parent->addChild(self); }else if(key=="item"){ argHook.indexIn(line); if(argHook.cap(1)=="<list>"){ }else if(argHook.cap(1)=="<function>"){ }else if(argHook.cap(1)=="<variable>"){ self->outBegin=argHook.cap(2).trimmed(); }else{ self->outBegin=line.trimmed(); } parent->addChild(self); }else if(key=="loop"){ self->outBegin="if True:"; function->append(self); }else if(key=="traverseloop"){ self->outBegin="if True:"; function->append(self); }else if(key=="traverse"){ self->outBegin="for traverse in "; self->outEnd=":"; function->append(self); }else if(key=="condition"){ self->outEnd=":"; if(parent->key=="branch"){ if(parent->data==0){ self->outBegin="if "; }else{ self->outBegin="elif "; } parent->data=1; }else if(parent->key=="loop"){ self->outBegin="while "; } argHook.indexIn(line); if(argHook.cap(1)=="<list>"){ }else if(argHook.cap(1)=="<function>"){ }else if(argHook.cap(1)=="<variable>"){ self->outBegin+=argHook.cap(2).trimmed(); }else{ self->outBegin+=line.trimmed(); } function->append(self); }else if(key=="return"){ self->outBegin="return "; argHook.indexIn(line); if(argHook.cap(1)=="<list>"){ }else if(argHook.cap(1)=="<function>"){ }else if(argHook.cap(1)=="<variable>"){ self->outBegin+=argHook.cap(2).trimmed(); }else{ self->outBegin+=line.trimmed(); } function->append(self); }else if(key=="execute"){ self->outBegin="exec("; self->outEnd=")"; argHook.indexIn(line); if(argHook.cap(1)=="<list>"){ }else if(argHook.cap(1)=="<function>"){ }else if(argHook.cap(1)=="<variable>"){ self->outBegin+=argHook.cap(2).trimmed(); }else{ self->outBegin+=line.trimmed(); } function->append(self); }else if(key=="break"){ self->outBegin = "break"; function->append(self); }else if(key=="continue"){ self->outBegin = "continue"; function->append(self); }else{ if(parent->key=="call"){ argHook.indexIn(line); if(argHook.cap(1)=="<list>"){ }else if(argHook.cap(1)=="<function>"){ }else if(argHook.cap(1)=="<variable>"){ self->outBegin+=argHook.cap(2).trimmed(); }else{ self->outBegin+=line.trimmed(); } parent->addChild(self); } } } if(function!=0) function->write(out); }else{ qDebug()<<"Can not open file "+path; } }