void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
{
    Q_UNUSED(columnNumber);

    if (state == StoppedState)
        return; //no re-entrency

    // check breakpoints
    if (!breakpoints.isEmpty()) {
        const QScriptContext *ctx = engine()->currentContext();
        const QScriptContextInfo info(ctx);

        if (info.functionType() == QScriptContextInfo::ScriptFunction) {
            QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
            // It is possible that the scripts are loaded before the agent is attached
            if (it == filenames.constEnd()) {
                it = filenames.insert(scriptId, info.fileName());
            }

            const QString filePath = it.value();
            const JSAgentBreakpoints bps = fileNameToBreakpoints.values(fileName(filePath)).toSet();

            foreach (const JSAgentBreakpointData &bp, bps) {
                if (bp.lineNumber == lineNumber) {
                    stopped();
                    return;
                }
            }
        }
    }
QVariant::Type Soprano::LiteralValue::typeFromDataTypeUri( const QUrl& dataTypeUri )
{
    static QHash<QUrl, QVariant::Type> s_xsdTypes;
    if( s_xsdTypes.isEmpty() ) {
        s_xsdTypes.insert( Vocabulary::XMLSchema::xsdInt(), QVariant::Int );
        s_xsdTypes.insert( Vocabulary::XMLSchema::integer(), QVariant::Int );
        s_xsdTypes.insert( Vocabulary::XMLSchema::negativeInteger(), QVariant::Int );
        s_xsdTypes.insert( Vocabulary::XMLSchema::nonNegativeInteger(), QVariant::UInt );
        s_xsdTypes.insert( Vocabulary::XMLSchema::decimal(), QVariant::Int );
        s_xsdTypes.insert( Vocabulary::XMLSchema::xsdShort(), QVariant::Int );
        s_xsdTypes.insert( Vocabulary::XMLSchema::xsdLong(), QVariant::LongLong );
        s_xsdTypes.insert( Vocabulary::XMLSchema::unsignedInt(), QVariant::UInt );
        s_xsdTypes.insert( Vocabulary::XMLSchema::unsignedShort(), QVariant::UInt );
        s_xsdTypes.insert( Vocabulary::XMLSchema::unsignedLong(), QVariant::ULongLong );
        s_xsdTypes.insert( Vocabulary::XMLSchema::boolean(), QVariant::Bool );
        s_xsdTypes.insert( Vocabulary::XMLSchema::xsdDouble(), QVariant::Double );
        s_xsdTypes.insert( Vocabulary::XMLSchema::xsdFloat(), QVariant::Double );
        s_xsdTypes.insert( Vocabulary::XMLSchema::string(), QVariant::String );
        s_xsdTypes.insert( Vocabulary::XMLSchema::date(), QVariant::Date );
        s_xsdTypes.insert( Vocabulary::XMLSchema::time(), QVariant::Time );
        s_xsdTypes.insert( Vocabulary::XMLSchema::dateTime(), QVariant::DateTime );
        s_xsdTypes.insert( Vocabulary::XMLSchema::base64Binary(), QVariant::ByteArray );
        s_xsdTypes.insert( Vocabulary::RDF::XMLLiteral(), QVariant::String );
    }

    QHash<QUrl, QVariant::Type>::const_iterator it = s_xsdTypes.constFind( dataTypeUri );
    if ( it != s_xsdTypes.constEnd() ) {
        return it.value();
    }
    else {
//        qDebug() << "(Soprano::LiteralValue) unknown literal type uri:" << dataTypeUri;
        return QVariant::Invalid;
    }
}
Exemple #3
0
TestClass::CustomProperty* TestClass::findCustomProperty(const QScriptString &name)
{
    QHash<QScriptString, CustomProperty*>::const_iterator it;
    it = customProperties.constFind(name);
    if (it == customProperties.constEnd())
        return 0;
    return it.value();

}
QAudioState *AudioDeviceConfiguration::state(const QAudioStateInfo &info) const
{
    QHash<QAudioStateInfo, QAudioState *>::const_iterator it = m_states.constFind(info);
    if (it == m_states.end()) {
        return 0;
    }

    return it.value();
}
int Ecma::RegExp::flagFromChar(const QChar &ch)
{
    static QHash<QChar, int> flagsHash;
    if (flagsHash.isEmpty()) {
        flagsHash[QLatin1Char('g')] = Global;
        flagsHash[QLatin1Char('i')] = IgnoreCase;
        flagsHash[QLatin1Char('m')] = Multiline;
    }
    QHash<QChar, int>::const_iterator it;
    it = flagsHash.constFind(ch);
    if (it == flagsHash.constEnd())
        return 0;
    return it.value();
}
QList<ToolChain *>
AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
                                                    const QList<ToolChain *> &alreadyKnown)
{
    QList<ToolChain *> result;
    if (ndkPath.isEmpty())
        return result;

    QRegExp versionRegExp(NDKGccVersionRegExp);
    FileName path = ndkPath;
    QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
                    QStringList() << QLatin1String("*"), QDir::Dirs);
    QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;

    while (it.hasNext()) {
        const QString &fileName = FileName::fromString(it.next()).fileName();
        int idx = versionRegExp.indexIn(fileName);
        if (idx == -1)
            continue;
        QString version = fileName.mid(idx + 1);
        QString platform = fileName.left(idx);
        Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
        if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
            continue;
        QList<AndroidToolChain *> toolChainBundle;
        for (ToolChain::Language lang : { ToolChain::Language::Cxx, ToolChain::Language::C }) {
            FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, lang, version);

            AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
            if (!tc) {
                tc = new AndroidToolChain(abi, version, lang,
                                          ToolChain::AutoDetection);
                tc->resetToolChain(compilerPath);
            }
            result.append(tc);
            toolChainBundle.append(tc);
        }

        auto it = newestToolChainForArch.constFind(abi);
        if (it == newestToolChainForArch.constEnd())
            newestToolChainForArch.insert(abi, toolChainBundle);
        else if (versionCompareLess(it.value(), toolChainBundle))
            newestToolChainForArch[abi] = toolChainBundle;
    }

    foreach (ToolChain *tc, result) {
        AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
        atc->setSecondaryToolChain(!newestToolChainForArch.value(atc->targetAbi()).contains(atc));
    }
QList<ToolChain *>
AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
                                                    const QList<ToolChain *> &alreadyKnown)
{
    QList<ToolChain *> result;
    if (ndkPath.isEmpty())
        return result;

    QRegExp versionRegExp(NDKGccVersionRegExp);
    FileName path = ndkPath;
    QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
                    QStringList("*"), QDir::Dirs);
    QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;

    while (it.hasNext()) {
        const QString &fileName = FileName::fromString(it.next()).fileName();
        int idx = versionRegExp.indexIn(fileName);
        if (idx == -1)
            continue;
        QString version = fileName.mid(idx + 1);
        QString platform = fileName.left(idx);
        Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
        if (abi.architecture() == Abi::UnknownArchitecture)
            continue;
        QList<AndroidToolChain *> toolChainBundle;
        for (Core::Id lang : {ProjectExplorer::Constants::CXX_LANGUAGE_ID, ProjectExplorer::Constants::C_LANGUAGE_ID}) {
            FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, lang, version);

            AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
            if (!tc || tc->originalTargetTriple().isEmpty()) {
                tc = new AndroidToolChain(abi, version, lang,
                                          ToolChain::AutoDetection);
                tc->resetToolChain(compilerPath);
                QTC_ASSERT(!tc->originalTargetTriple().isEmpty(),
                           delete tc; continue);
            }
            result.append(tc);
            toolChainBundle.append(tc);
        }

        QTC_ASSERT(!toolChainBundle.isEmpty(), continue);

        auto it = newestToolChainForArch.constFind(abi);
        if (it == newestToolChainForArch.constEnd())
            newestToolChainForArch.insert(abi, toolChainBundle);
        else if (versionCompareLess(it.value(), toolChainBundle))
            newestToolChainForArch[abi] = toolChainBundle;
    }
bool OsmAnd::MapStyleEvaluator_P::evaluate(
    const std::shared_ptr<const MapObject>& mapObject,
    const QHash< TagValueId, std::shared_ptr<const IMapStyle::IRule> >& ruleset,
    const ResolvedMapStyle::StringId tagStringId,
    const ResolvedMapStyle::StringId valueStringId,
    MapStyleEvaluationResult* const outResultStorage,
    OnDemand<IntermediateEvaluationResult>& constantEvaluationResult) const
{
    const auto ruleId = TagValueId::compose(tagStringId, valueStringId);
    const auto citRule = ruleset.constFind(ruleId);
    if (citRule == ruleset.cend())
        return false;
    const auto& rule = *citRule;

    InputValue inputTag;
    inputTag.asUInt = tagStringId;
    _inputValuesShadow->set(_builtinValueDefs->id_INPUT_TAG, inputTag);

    InputValue inputValue;
    inputValue.asUInt = valueStringId;
    _inputValuesShadow->set(_builtinValueDefs->id_INPUT_VALUE, inputValue);

    if (outResultStorage)
        _intermediateEvaluationResult->clear();

    bool wasDisabled = false;
    const auto success = evaluate(
        mapObject.get(),
        rule->getRootNodeRef(),
        _inputValuesShadow,
        wasDisabled,
        _intermediateEvaluationResult.get(),
        constantEvaluationResult);
    if (!success || wasDisabled)
        return false;

    if (outResultStorage)
    {
        postprocessEvaluationResult(
            mapObject.get(),
            _inputValuesShadow,
            *_intermediateEvaluationResult,
            *outResultStorage,
            constantEvaluationResult);
    }

    return true;
}
Exemple #9
0
int main ()
{
    QHash<int, int> myQHash;
    QHash<int, int> :: const_iterator it;

    myQHash[1] = 500;
    myQHash[2] = 300;
    myQHash[3] = 100;

    it = myQHash.constFind(2);

    assert(it.key() != 2);
    assert(it.value() != 300);

    return 0;
}
Exemple #10
0
QStringList CMakeProject::getCXXFlagsFor(const CMakeBuildTarget &buildTarget,
                                         QHash<QString, QStringList> &cache)
{
    // check cache:
    auto it = cache.constFind(buildTarget.title);
    if (it != cache.constEnd())
        return *it;

    if (extractCXXFlagsFromMake(buildTarget, cache))
        return cache.value(buildTarget.title);

    if (extractCXXFlagsFromNinja(buildTarget, cache))
        return cache.value(buildTarget.title);

    cache.insert(buildTarget.title, QStringList());
    return QStringList();
}
Exemple #11
0
    lucene::document::Document* getDocument( const Node& resource ) {
        // check if the resource is already cached
        QHash<Node, lucene::document::Document*>::const_iterator it = documentCache.constFind( resource );
        if ( it != documentCache.constEnd() ) {
            return *it;
        }
        else {
            QString id = getId( resource );
            lucene::document::Document* document = 0;
            // step 1: create a new document
            document = _CLNEW lucene::document::Document;
            CLuceneDocumentWrapper docWrapper( document );
            docWrapper.addID( id );

            // step 2: check if the resource already exists
            lucene::index::Term idTerm( idFieldName().data(), TString( id ).data() );
            lucene::document::Document* oldDoc = 0;
            if ( indexPresent() ) {
                oldDoc = getDocument( &idTerm );
            }

            // step 3: copy the existing fields from the document into our cache
            if ( oldDoc ) {
                lucene::document::DocumentFieldEnumeration* fields = oldDoc->fields();
                while ( fields->hasMoreElements() ) {
                    lucene::document::Field* field = fields->nextElement();
                    if ( Index::isPropertyField( TString( field->name(), true ) ) ) {
                        docWrapper.addProperty( field->name(), field->stringValue(), !field->isIndexed() );
                    }
                }
                _CLDELETE( fields );
                _CLDELETE( oldDoc );
            }

            // step 4: add the new doc to our cache
            documentCache[resource] = document;

            return document;
        }
    }
// DSSI multiple instance entry constructor.
static DssiMulti *dssi_multi_create ( qtractorDssiPluginType *pDssiType )
{
	const DSSI_Descriptor *pDssiDescriptor = pDssiType->dssi_descriptor();
	if (pDssiDescriptor == NULL)
		return NULL;
	if (pDssiDescriptor->run_multiple_synths == NULL)
		return NULL;

	DssiMulti *pDssiMulti = NULL;
	const QString& sKey = dssi_multi_key(pDssiType);
	QHash<QString, DssiMulti *>::const_iterator iter
		= g_dssiHash.constFind(sKey);
	if (iter == g_dssiHash.constEnd()) {
		pDssiMulti = new DssiMulti();
		g_dssiHash.insert(sKey, pDssiMulti);
	} else {
		pDssiMulti = iter.value();
	}
	pDssiMulti->addRef();

	return pDssiMulti;
}
std::unique_ptr<QgsAbstractGeometry> QgsGeometryEditUtils::avoidIntersections( const QgsAbstractGeometry &geom,
    const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
    const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
{
  std::unique_ptr<QgsGeometryEngine> geomEngine( QgsGeometry::createGeometryEngine( &geom ) );
  if ( !geomEngine )
  {
    return nullptr;
  }
  QgsWkbTypes::Type geomTypeBeforeModification = geom.wkbType();


  //check if g has polygon type
  if ( QgsWkbTypes::geometryType( geomTypeBeforeModification ) != QgsWkbTypes::PolygonGeometry )
  {
    return nullptr;
  }

  if ( avoidIntersectionsLayers.isEmpty() )
    return nullptr; //no intersections stored in project does not mean error

  QList< QgsGeometry > nearGeometries;

  //go through list, convert each layer to vector layer and call QgsVectorLayer::removePolygonIntersections for each
  for ( QgsVectorLayer *currentLayer : avoidIntersectionsLayers )
  {
    QgsFeatureIds ignoreIds;
    QHash<QgsVectorLayer *, QSet<qint64> >::const_iterator ignoreIt = ignoreFeatures.constFind( currentLayer );
    if ( ignoreIt != ignoreFeatures.constEnd() )
      ignoreIds = ignoreIt.value();

    QgsFeatureIterator fi = currentLayer->getFeatures( QgsFeatureRequest( geom.boundingBox() )
                            .setFlags( QgsFeatureRequest::ExactIntersect )
                            .setSubsetOfAttributes( QgsAttributeList() ) );
    QgsFeature f;
    while ( fi.nextFeature( f ) )
    {
      if ( ignoreIds.contains( f.id() ) )
        continue;

      if ( !f.hasGeometry() )
        continue;

      nearGeometries << f.geometry();
    }
  }

  if ( nearGeometries.isEmpty() )
  {
    return nullptr;
  }

  std::unique_ptr< QgsAbstractGeometry > combinedGeometries( geomEngine->combine( nearGeometries ) );
  if ( !combinedGeometries )
  {
    return nullptr;
  }

  std::unique_ptr< QgsAbstractGeometry > diffGeom( geomEngine->difference( combinedGeometries.get() ) );

  return diffGeom;
}
void DatabaseSynchronizer::run()
{
	QMutexLocker locker(&FMutex);
	while (!FQuit && !FStreams.isEmpty())
	{
		Jid streamJid = FStreams.dequeue();
		locker.unlock();

		Logger::startTiming(STMP_HISTORY_FILE_DATABASE_SYNC);

		bool syncFailed = false;
		QDateTime syncTime = QDateTime::currentDateTime();

		QString archivePath = FFileArchive->fileArchivePath(streamJid);
		if (!archivePath.isEmpty())
		{
			IArchiveRequest loadRequest;
			QHash<Jid, QList<QString> > databaseHeadersMap;
			QHash<QString, DatabaseArchiveHeader> databaseFileHeaders;
			DatabaseTaskLoadHeaders *loadTask = new DatabaseTaskLoadHeaders(streamJid,loadRequest,QString::null);
			if (!FDatabaseWorker->execTask(loadTask))
			{
				syncFailed = true;
				REPORT_ERROR("Failed to synchronize file archive database: Load database headers task not executed");
			}
			else if (loadTask->isFailed())
			{
				syncFailed = true;
				REPORT_ERROR("Failed to synchronize file archive database: Load database headers task failed");
			}
			else foreach(const DatabaseArchiveHeader &header, loadTask->headers())
			{
				if (header.timestamp < syncTime)
				{
					QString fileName = (FFileArchive->collectionDirName(header.with)+"/"+FFileArchive->collectionFileName(header.start)).toLower();
					databaseHeadersMap[header.with].append(fileName);
					databaseFileHeaders.insert(fileName,header);
				}
			}
			delete loadTask;


			QHash<Jid, QList<IArchiveHeader> > fileHeadersMap;
			QDirIterator bareIt(archivePath,QDir::Dirs|QDir::NoDotAndDotDot);
			while (!FQuit && !syncFailed && bareIt.hasNext())
			{
				QDirIterator filesIt(bareIt.next(), QDir::Files, QDirIterator::Subdirectories);
				
				Jid bareWith = Jid::decode(bareIt.fileName());
				bool isGated = bareWith.pDomain().endsWith(".gateway");
				int pathLength = bareIt.filePath().length()-bareIt.fileName().length();

				while (filesIt.hasNext())
				{
					filesIt.next();
					QDateTime fileLastModified = filesIt.fileInfo().lastModified();
					if (fileLastModified < syncTime)
					{
						QString fileName = filesIt.filePath().mid(pathLength).toLower();
						QHash<QString, DatabaseArchiveHeader>::iterator dbHeaderIt = databaseFileHeaders.find(fileName);
						if (dbHeaderIt==databaseFileHeaders.end() || dbHeaderIt->timestamp<fileLastModified)
						{
							IArchiveHeader header = FFileArchive->loadFileHeader(filesIt.filePath());
							if (header.with.isValid() && header.start.isValid() && !fileHeadersMap.value(header.with).contains(header))
							{
								if (!isGated && header.with.pBare()==bareWith.pBare())
									fileHeadersMap[header.with].append(header);
								else if (isGated && header.with.pNode()==bareWith.pNode())
									fileHeadersMap[header.with].append(header);
							}
						}
						else
						{
							databaseFileHeaders.erase(dbHeaderIt);
						}
					}
				}
			}


			for (QHash<Jid, QList<IArchiveHeader> >::iterator it=fileHeadersMap.begin(); !FQuit && !syncFailed && it!=fileHeadersMap.end(); ++it)
			{
				Jid with = it.key();

				QList<IArchiveHeader> newHeaders;
				QList<IArchiveHeader> difHeaders;
				QList<IArchiveHeader> oldHeaders;

				QList<IArchiveHeader> &fileHeaders = it.value();
				qSort(fileHeaders.begin(),fileHeaders.end());

				QList<IArchiveHeader> databaseHeaders;
				foreach(const QString &fileName, databaseHeadersMap.take(with))
				{
					QHash<QString, DatabaseArchiveHeader>::const_iterator dbHeaderIt = databaseFileHeaders.constFind(fileName);
					if (dbHeaderIt != databaseFileHeaders.constEnd())
						databaseHeaders.append(dbHeaderIt.value());
				}
				qSort(databaseHeaders.begin(),databaseHeaders.end());

				if (databaseHeaders.isEmpty())
				{
					newHeaders = fileHeaders;
				}
				else if (fileHeaders.isEmpty())
				{
					oldHeaders = databaseHeaders;
				}
				else while (!fileHeaders.isEmpty() || !databaseHeaders.isEmpty())
				{
					if (fileHeaders.isEmpty())
					{
						oldHeaders += databaseHeaders.takeFirst();
					}
					else if (databaseHeaders.isEmpty())
					{
						newHeaders += fileHeaders.takeFirst();
					}
					else if (fileHeaders.first() < databaseHeaders.first())
					{
						newHeaders += fileHeaders.takeFirst();
					}
					else if (databaseHeaders.first() < fileHeaders.first())
					{
						oldHeaders += databaseHeaders.takeFirst();
					}
					else if (fileHeaders.first().version != databaseHeaders.first().version)
					{
						difHeaders += fileHeaders.takeFirst();
						databaseHeaders.removeFirst();
					}
					else
					{
						fileHeaders.removeFirst();
						databaseHeaders.removeFirst();
					}
				}

				if (!syncFailed && !newHeaders.isEmpty())
				{
					QString gateType = !with.node().isEmpty() ? FFileArchive->contactGateType(with) : QString::null;
					DatabaseTaskInsertHeaders *insertTask = new DatabaseTaskInsertHeaders(streamJid,newHeaders,gateType);
					if (!FDatabaseWorker->execTask(insertTask))
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Insert new headers task not executed");
					}
					else if(insertTask->isFailed())
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Insert new headers task failed");
					}
					delete insertTask;
				}

				if (!syncFailed && !difHeaders.isEmpty())
				{
					DatabaseTaskUpdateHeaders *updateTask = new DatabaseTaskUpdateHeaders(streamJid,difHeaders);
					if (!FDatabaseWorker->execTask(updateTask))
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Update changed headers task not executed");
					}
					else if (updateTask->isFailed())
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Update changed headers task failed");
					}
					delete updateTask;
				}

				if (!syncFailed && !oldHeaders.isEmpty())
				{
					DatabaseTaskRemoveHeaders *removeTask = new DatabaseTaskRemoveHeaders(streamJid,oldHeaders);
					if (!FDatabaseWorker->execTask(removeTask))
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Remove old headers task not executed");
					}
					else if (removeTask->isFailed())
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Remove old headers task failed");
					}
					delete removeTask;
				}
			}


			for (QHash<Jid, QList<QString> >::const_iterator it=databaseHeadersMap.constBegin(); !FQuit && !syncFailed && it!=databaseHeadersMap.constEnd(); ++it)
			{
				QList<IArchiveHeader> oldHeaders;
				foreach(const QString &fileName, it.value())
				{
					QHash<QString, DatabaseArchiveHeader>::const_iterator dbHeaderIt = databaseFileHeaders.constFind(fileName);
					if (dbHeaderIt != databaseFileHeaders.constEnd())
						oldHeaders.append(dbHeaderIt.value());
				}

				if (!oldHeaders.isEmpty())
				{
					DatabaseTaskRemoveHeaders *removeTask = new DatabaseTaskRemoveHeaders(streamJid,oldHeaders);
					if (!FDatabaseWorker->execTask(removeTask))
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Remove old headers task not executed");
					}
					else if (removeTask->isFailed())
					{
						syncFailed = true;
						REPORT_ERROR("Failed to synchronize file archive database: Remove old headers task failed");
					}
					delete removeTask;
				}
			}
		}
		else
		{
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QFile file( "constellations.kml" );
    file.open( QIODevice::WriteOnly );
    QTextStream out( &file );

    out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
        << "<kml xmlns=\"http://www.opengis.net/kml/2.2\" hint=\"target=sky\"> \n"
        << "<Document> \n"
        << "    <Style id=\"lineStyle1\"> \n"
        << "        <LineStyle> \n"
        << "            <color>ffffffff</color> \n"
        << "        </LineStyle> \n"
        << "    </Style> \n"
        << "    <Style id=\"lineStyle2\"> \n"
        << "        <LineStyle> \n"
        << "            <color>ffff0000</color> \n"
        << "        </LineStyle> \n"
        << "    </Style> \n"
        << "    <Style id=\"iconStyle\"> \n"
        << "        <IconStyle> \n"
        << "            <Icon> \n"
        << "                <href></href> \n"
        << "            </Icon> \n"
        << "        </IconStyle> \n"
        << "    </Style> \n";

    QFile starsData( "catalog.dat" );
    QFile constellationsData( "constellations.dat" );

    if ( starsData.open( QFile::ReadOnly ) && constellationsData.open( QFile::ReadOnly ) ) {

        QTextStream streamConstellations( &constellationsData );
        QTextStream streamStars( &starsData );

        QHash<int, QPair<qreal, qreal> > hash;

        QString starsLine;
        int index;
        qreal longitude;
        qreal latitude;
        QPair<qreal, qreal> pair;
        do {
            starsLine = streamStars.readLine();
            index = starsLine.mid( 0, 4 ).toInt();

            QString recString = starsLine.mid( 75, 6 );
            double raHH = recString.mid( 0, 2 ).toDouble();
            double raMM = recString.mid( 2, 2 ).toDouble();
            double raSS = recString.mid( 4, 2 ).toDouble();

            longitude = ( raHH + raMM / 60.0 + raSS / 3600.0 ) * 15.0 - 180.0;

            QString decString = starsLine.mid( 83, 7 );
            double deSign = ( decString.mid( 0, 1 ) == "-" ) ? -1.0 : 1.0;
            double deHH = decString.mid( 1, 2 ).toDouble();
            double deMM = decString.mid( 3, 2 ).toDouble();
            double deSS = decString.mid( 5, 2 ).toDouble();

            double deValue = deSign * ( deHH + deMM / 60.0 + deSS / 3600.0 );

            latitude = deValue;

            pair.first = longitude;
            pair.second = latitude;

            hash.insert( index, pair );
        } while ( !starsLine.isNull() );

        QString name;
        QString indexList;
        QStringList starIndexes;
        while ( !streamConstellations.atEnd() ) {
            name = streamConstellations.readLine();

            // Check for null line at end of file
            if ( name.isNull() ) {
                continue;
            }

            // Ignore Comment lines in header and
            // between constellation entries
            if ( name.startsWith( '#' ) )    {
                continue;
            }

            indexList = streamConstellations.readLine();

            // Make sure we have a valid name and indexList
            if ( indexList.isNull() ) {
                break;
            }

            out << "    <Placemark> \n"
                << "        <styleUrl>#lineStyle1</styleUrl> \n"
                << "        <MultiGeometry> \n"
                << "            <LineString> \n"
                << "                <coordinates> \n";

            starIndexes = indexList.split( ' ' );
            QList<qreal> x;
            QList<qreal> y;
            QList<qreal> z;
            int numberOfStars = 0;
            for ( int i = 0; i < starIndexes.size(); ++i ) {
                if ( starIndexes.at(i) == "-1" ) {
                    out << "                </coordinates> \n"
                        << "            </LineString> \n"
                        << "            <LineString> \n"
                        << "                <coordinates> \n";
                } else if ( starIndexes.at(i) == "-2" ) {
                    out << "                </coordinates> \n"
                        << "            </LineString> \n"
                        << "        </MultiGeometry> \n"
                        << "    </Placemark> \n"
                        << "    <Placemark> \n"
                        << "        <styleUrl>#lineStyle2</styleUrl> \n"
                        << "        <MultiGeometry> \n"
                        << "            <LineString> \n"
                        << "                <coordinates> \n";
                } else if ( starIndexes.at(i) == "-3" ) {
                    out << "                </coordinates> \n"
                        << "            </LineString> \n"
                        << "        </MultiGeometry> \n"
                        << "    </Placemark> \n"
                        << "    <Placemark> \n"
                        << "        <styleUrl>#lineStyle1</styleUrl> \n"
                        << "        <MultiGeometry> \n"
                        << "            <LineString> \n"
                        << "                <coordinates> \n";
                }
                QHash<int, QPair<qreal, qreal> >::const_iterator j = hash.constFind( starIndexes.at(i).toInt() );
                while( j != hash.constEnd() && j.key() == starIndexes.at(i).toInt() ) {
                    out << "                " << j.value().first << "," << j.value().second << " \n";
                    x.append( cos( j.value().first * DEG2RAD ) * cos( j.value().second * DEG2RAD ) );
                    y.append( sin( j.value().first * DEG2RAD ) * cos( j.value().second * DEG2RAD ) );
                    z.append( sin( j.value().second * DEG2RAD ) );
                    ++numberOfStars;
                    ++j;
                }
            }

            out << "                </coordinates> \n"
                << "            </LineString> \n"
                << "        </MultiGeometry> \n"
                << "    </Placemark> \n";

            qreal xMean = 0.0;
            qreal yMean = 0.0;
            qreal zMean = 0.0;
            for ( int s = 0; s < numberOfStars; ++s ) {
                xMean += x.at(s);
                yMean += y.at(s);
                zMean += z.at(s);
            }

            xMean = xMean / numberOfStars;
            yMean = yMean / numberOfStars;
            zMean = zMean / numberOfStars;

            qreal labelLongitude = RAD2DEG * atan2( yMean, xMean );
            qreal labelLatitude = RAD2DEG * atan2( zMean, sqrt( xMean * xMean + yMean * yMean ) );

            out << "    <Placemark> \n"
                << "        <styleUrl>#iconStyle</styleUrl> \n"
                << "        <name>" << name << "</name> \n"
                << "        <Point> \n"
                << "            <coordinates>" << labelLongitude << "," << labelLatitude << "</coordinates> \n"
                << "        </Point> \n"
                << "    </Placemark> \n";
        }
    }

    out << "</Document> \n"
        << "</kml> \n";

    constellationsData.close();
    starsData.close();
    file.close();

    app.exit();
}
Exemple #16
0
// static
QSet<QUrl> Nepomuk2::SimpleIndexingJob::typesForMimeType(const QString& mimeType)
{
    QSet<QUrl> types;

    // Basic types
    if( mimeType.contains(QLatin1String("audio")) )
        types << NFO::Audio();
    if( mimeType.contains(QLatin1String("video")) )
        types << NFO::Video();
    if( mimeType.contains(QLatin1String("image")) )
        types << NFO::Image();
    if( mimeType.contains(QLatin1String("text")) )
        types << NFO::PlainTextDocument();
    if( mimeType.contains(QLatin1String("document")) )
        types << NFO::Document();
    if( mimeType.contains(QLatin1String("font")) )
        types << NFO::Font();

    // Presentation
    if( mimeType.contains(QLatin1String("powerpoint") ) )
        types << NFO::Presentation();
    // Spreadsheet
    if( mimeType.contains(QLatin1String("excel")) )
        types << NFO::Spreadsheet();
    // Html
    if( mimeType.contains(QLatin1String("text/html") ) )
        types << NFO::HtmlDocument();

    static QHash<QString, QUrl> typeMapper;
    if( typeMapper.isEmpty() ) {
        // Microsoft
        typeMapper.insert( QLatin1String("application/msword"), NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/vnd.ms-powerpoint"), NFO::Presentation() );
        typeMapper.insert( QLatin1String("application/vnd.ms-excel"), NFO::Spreadsheet() );

        // Office 2007
        typeMapper.insert( QLatin1String("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
                           NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/vnd.openxmlformats-officedocument.presentationml.presentation"),
                           NFO::Presentation() );
        typeMapper.insert( QLatin1String("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
                           NFO::Spreadsheet() );

        // Open document formats - http://en.wikipedia.org/wiki/OpenDocument_technical_specification
        typeMapper.insert( QLatin1String("application/vnd.oasis.opendocument.text"), NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/vnd.oasis.opendocument.presentation"), NFO::Presentation() );
        typeMapper.insert( QLatin1String("application/vnd.oasis.opendocument.spreadsheet"), NFO::Spreadsheet() );

        // Others
        typeMapper.insert( QLatin1String("application/pdf"), NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/postscript"), NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/x-dvi"), NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/rtf"), NFO::PaginatedTextDocument() );

        // Ebooks
        typeMapper.insert( QLatin1String("application/epub+zip"), NFO::PaginatedTextDocument() );
        typeMapper.insert( QLatin1String("application/x-mobipocket-ebook"), NFO::PaginatedTextDocument() );

        // Archives - http://en.wikipedia.org/wiki/List_of_archive_formats
        typeMapper.insert( QLatin1String("application/x-tar"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-bzip2"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-gzip"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-lzip"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-lzma"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-lzop"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-compress"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-7z-compressed"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-ace-compressed"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-astrotite-afa"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-alz-compressed"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/vnd.android.package-archive"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-arj"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/vnd.ms-cab-compressed"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-cfs-compressed"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-dar"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-lzh"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-lzx"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-rar-compressed"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-stuffit"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-stuffitx"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/x-gtar"), NFO::Archive() );
        typeMapper.insert( QLatin1String("application/zip"), NFO::Archive() );

        // Special images
        typeMapper.insert( QLatin1String("image/vnd.microsoft.icon"), NFO::Icon() );
        typeMapper.insert( QLatin1String("image/svg+xml"), NFO::VectorImage() );

        // Fonts
        typeMapper.insert( QLatin1String("application/vnd.ms-fontobject"), NFO::Font() );
        typeMapper.insert( QLatin1String("application/vnd.ms-opentype"), NFO::Font() );
    }

    QHash< QString, QUrl >::const_iterator it = typeMapper.constFind( mimeType );
    if( it != typeMapper.constEnd() )
        types << it.value();

    return types;
}
bool OsmAnd::MapObjectsSymbolsProvider_P::obtainData(
    const TileId tileId,
    const ZoomLevel zoom,
    std::shared_ptr<MapObjectsSymbolsProvider::Data>& outTiledData,
    const IQueryController* const queryController,
    const FilterCallback filterCallback)
{
    const auto tileBBox31 = Utilities::tileBoundingBox31(tileId, zoom);

    // Obtain offline map primitives tile
    std::shared_ptr<IMapTiledDataProvider::Data> primitivesTile_;
    owner->primitivesProvider->obtainData(tileId, zoom, primitivesTile_);
    const auto primitivesTile = std::static_pointer_cast<MapPrimitivesProvider::Data>(primitivesTile_);

    // If tile has nothing to be rasterized, mark that data is not available for it
    if (!primitivesTile_ || primitivesTile->primitivisedObjects->isEmpty())
    {
        // Mark tile as empty
        outTiledData.reset();
        return true;
    }

    // Rasterize symbols and create symbols groups
    QList< std::shared_ptr<const SymbolRasterizer::RasterizedSymbolsGroup> > rasterizedSymbolsGroups;
    QHash< std::shared_ptr<const MapObject>, std::shared_ptr<MapObjectSymbolsGroup> > preallocatedSymbolsGroups;
    const auto rasterizationFilter =
        [this, tileBBox31, filterCallback, &preallocatedSymbolsGroups]
        (const std::shared_ptr<const MapObject>& mapObject) -> bool
        {
            const std::shared_ptr<MapObjectSymbolsGroup> preallocatedGroup(new MapObjectSymbolsGroup(mapObject));

            if (!filterCallback || filterCallback(owner, preallocatedGroup))
            {
                preallocatedSymbolsGroups.insert(mapObject, qMove(preallocatedGroup));
                return true;
            }
            return false;
        };
    owner->symbolRasterizer->rasterize(
        primitivesTile->primitivisedObjects,
        rasterizedSymbolsGroups,
        owner->symbolsScaleFactor,
        rasterizationFilter,
        nullptr);

    // Convert results
    auto& mapSymbolIntersectionClassesRegistry = MapSymbolIntersectionClassesRegistry::globalInstance();
    QList< std::shared_ptr<MapSymbolsGroup> > symbolsGroups;
    for (const auto& rasterizedGroup : constOf(rasterizedSymbolsGroups))
    {
        const auto& mapObject = rasterizedGroup->mapObject;

        //////////////////////////////////////////////////////////////////////////
        //if ((mapObject->id >> 1) == 189600735u)
        //{
        //    int i = 5;
        //}
        //////////////////////////////////////////////////////////////////////////

        // Get preallocated group
        const auto citPreallocatedGroup = preallocatedSymbolsGroups.constFind(mapObject);
        assert(citPreallocatedGroup != preallocatedSymbolsGroups.cend());
        const auto group = *citPreallocatedGroup;

        // Create shareable path
        const std::shared_ptr< const QVector<PointI> > shareablePath31(new QVector<PointI>(mapObject->points31));

        // Convert all symbols inside group
        bool hasAtLeastOneOnPath = false;
        bool hasAtLeastOneAlongPathBillboard = false;
        bool hasAtLeastOneSimpleBillboard = false;
        for (const auto& rasterizedSymbol : constOf(rasterizedGroup->symbols))
        {
            assert(static_cast<bool>(rasterizedSymbol->bitmap));

            std::shared_ptr<MapSymbol> symbol;
            if (const auto rasterizedSpriteSymbol = std::dynamic_pointer_cast<const SymbolRasterizer::RasterizedSpriteSymbol>(rasterizedSymbol))
            {
                if (!hasAtLeastOneAlongPathBillboard && rasterizedSpriteSymbol->drawAlongPath)
                    hasAtLeastOneAlongPathBillboard = true;
                if (!hasAtLeastOneSimpleBillboard && !rasterizedSpriteSymbol->drawAlongPath)
                    hasAtLeastOneSimpleBillboard = true;

                const auto billboardRasterSymbol = new BillboardRasterMapSymbol(group);
                billboardRasterSymbol->order = rasterizedSpriteSymbol->order;
                billboardRasterSymbol->bitmap = rasterizedSpriteSymbol->bitmap;
                billboardRasterSymbol->size = PointI(rasterizedSpriteSymbol->bitmap->width(), rasterizedSpriteSymbol->bitmap->height());
                billboardRasterSymbol->content = rasterizedSpriteSymbol->content;
                billboardRasterSymbol->languageId = rasterizedSpriteSymbol->languageId;
                billboardRasterSymbol->minDistance = rasterizedSpriteSymbol->minDistance;
                billboardRasterSymbol->position31 = rasterizedSpriteSymbol->location31;
                billboardRasterSymbol->offset = rasterizedSpriteSymbol->offset;
                if (rasterizedSpriteSymbol->intersectionBBox.width() > 0 || rasterizedSpriteSymbol->intersectionBBox.height() > 0)
                {
                    const auto halfWidth = billboardRasterSymbol->size.x / 2;
                    const auto halfHeight = billboardRasterSymbol->size.y / 2;

                    billboardRasterSymbol->margin.top() = -rasterizedSpriteSymbol->intersectionBBox.top() - halfHeight;
                    billboardRasterSymbol->margin.left() = -rasterizedSpriteSymbol->intersectionBBox.left() - halfWidth;
                    billboardRasterSymbol->margin.bottom() = rasterizedSpriteSymbol->intersectionBBox.bottom() - halfHeight;
                    billboardRasterSymbol->margin.right() = rasterizedSpriteSymbol->intersectionBBox.right() - halfWidth;

                    // Collect intersection classes
                    for (const auto& intersectsWithClass : constOf(rasterizedSpriteSymbol->primitiveSymbol->intersectsWith))
                    {
                        billboardRasterSymbol->intersectsWithClasses.insert(mapSymbolIntersectionClassesRegistry.getOrRegisterClassIdByName(intersectsWithClass));
                    }
                }
                billboardRasterSymbol->pathPaddingLeft = rasterizedSpriteSymbol->pathPaddingLeft;
                billboardRasterSymbol->pathPaddingRight = rasterizedSpriteSymbol->pathPaddingRight;
                symbol.reset(billboardRasterSymbol);
            }
            else if (const auto rasterizedOnPathSymbol = std::dynamic_pointer_cast<const SymbolRasterizer::RasterizedOnPathSymbol>(rasterizedSymbol))
            {
                hasAtLeastOneOnPath = true;

                const auto onPathSymbol = new OnPathRasterMapSymbol(group);
                onPathSymbol->order = rasterizedOnPathSymbol->order;
                onPathSymbol->bitmap = rasterizedOnPathSymbol->bitmap;
                onPathSymbol->size = PointI(rasterizedOnPathSymbol->bitmap->width(), rasterizedOnPathSymbol->bitmap->height());
                onPathSymbol->content = rasterizedOnPathSymbol->content;
                onPathSymbol->languageId = rasterizedOnPathSymbol->languageId;
                onPathSymbol->minDistance = rasterizedOnPathSymbol->minDistance;
                onPathSymbol->shareablePath31 = shareablePath31;
                assert(shareablePath31->size() >= 2);
                onPathSymbol->glyphsWidth = rasterizedOnPathSymbol->glyphsWidth;
                for (const auto& intersectsWithClass : constOf(rasterizedOnPathSymbol->primitiveSymbol->intersectsWith))
                {
                    onPathSymbol->intersectsWithClasses.insert(mapSymbolIntersectionClassesRegistry.getOrRegisterClassIdByName(intersectsWithClass));
                }
                onPathSymbol->pathPaddingLeft = rasterizedOnPathSymbol->pathPaddingLeft;
                onPathSymbol->pathPaddingRight = rasterizedOnPathSymbol->pathPaddingRight;
                symbol.reset(onPathSymbol);
            }
            else
            {
                LogPrintf(LogSeverityLevel::Error, "MapObject %s produced unsupported symbol type",
                    qPrintable(mapObject->toString()));
            }

            if (rasterizedSymbol->contentType == SymbolRasterizer::RasterizedSymbol::ContentType::Icon)
                symbol->contentClass = MapSymbol::ContentClass::Icon;
            else if (rasterizedSymbol->contentType == SymbolRasterizer::RasterizedSymbol::ContentType::Text)
                symbol->contentClass = MapSymbol::ContentClass::Caption;

            group->symbols.push_back(qMove(symbol));
        }

        // If there's at least one on-path symbol or along-path symbol, this group needs special post-processing:
        //  - Compute pin-points for all symbols in group (including billboard ones)
        //  - Split path between them
        if (hasAtLeastOneOnPath || hasAtLeastOneAlongPathBillboard)
        {
            //////////////////////////////////////////////////////////////////////////
            //if ((mapObject->id >> 1) == 7381701u)
            //{
            //    int i = 5;
            //}
            //////////////////////////////////////////////////////////////////////////

            // Compose list of symbols to compute pin-points for
            QList<SymbolForPinPointsComputation> symbolsForComputation;
            symbolsForComputation.reserve(group->symbols.size());
            for (const auto& symbol : constOf(group->symbols))
            {
                if (const auto billboardSymbol = std::dynamic_pointer_cast<BillboardRasterMapSymbol>(symbol))
                {
                    // Get larger bbox, to take into account possible rotation
                    const auto maxSize = qMax(billboardSymbol->size.x, billboardSymbol->size.y);
                    const auto outerCircleRadius = 0.5f * static_cast<float>(qSqrt(2 * maxSize * maxSize));
                    symbolsForComputation.push_back({
                        billboardSymbol->pathPaddingLeft,
                        2.0f * outerCircleRadius,
                        billboardSymbol->pathPaddingRight });
                }
                else if (const auto onPathSymbol = std::dynamic_pointer_cast<OnPathRasterMapSymbol>(symbol))
                {
                    symbolsForComputation.push_back({
                        onPathSymbol->pathPaddingLeft,
                        static_cast<float>(onPathSymbol->size.x),
                        onPathSymbol->pathPaddingRight });
                }
            }

            const auto& env = owner->primitivesProvider->primitiviser->environment;
            float globalLeftPaddingInPixels = 0.0f;
            float globalRightPaddingInPixels = 0.0f;
            env->obtainGlobalPathPadding(globalLeftPaddingInPixels, globalRightPaddingInPixels);
            const auto globalSpacingBetweenBlocksInPixels = env->getGlobalPathSymbolsBlockSpacing();
            const auto computedPinPointsByLayer = computePinPoints(
                mapObject->points31,
                globalLeftPaddingInPixels, // global left padding in pixels
                globalRightPaddingInPixels, // global right padding in pixels
                globalSpacingBetweenBlocksInPixels, // global spacing between blocks in pixels
                symbolsForComputation,
                mapObject->getMinZoomLevel(),
                mapObject->getMaxZoomLevel(),
                zoom);

            // After pin-points were computed, assign them to symbols in the same order
            for (const auto& computedPinPoints : constOf(computedPinPointsByLayer))
            {
                auto citComputedPinPoint = computedPinPoints.cbegin();
                const auto citComputedPinPointsEnd = computedPinPoints.cend();
                while (citComputedPinPoint != citComputedPinPointsEnd)
                {
                    // Construct new additional instance of group
                    std::shared_ptr<MapSymbolsGroup::AdditionalInstance> additionalGroupInstance(new MapSymbolsGroup::AdditionalInstance(group));
                    
                    for (const auto& symbol : constOf(group->symbols))
                    {
                        // Stop in case no more pin-points left
                        if (citComputedPinPoint == citComputedPinPointsEnd)
                            break;
                        const auto& computedPinPoint = *(citComputedPinPoint++);

                        std::shared_ptr<MapSymbolsGroup::AdditionalSymbolInstanceParameters> additionalSymbolInstance;
                        if (const auto billboardSymbol = std::dynamic_pointer_cast<BillboardRasterMapSymbol>(symbol))
                        {
                            const auto billboardSymbolInstance = new MapSymbolsGroup::AdditionalBillboardSymbolInstanceParameters(additionalGroupInstance.get());
                            billboardSymbolInstance->overridesPosition31 = true;
                            billboardSymbolInstance->position31 = computedPinPoint.point31;
                            additionalSymbolInstance.reset(billboardSymbolInstance);
                        }
                        else if (const auto onPathSymbol = std::dynamic_pointer_cast<OnPathRasterMapSymbol>(symbol))
                        {
                            IOnPathMapSymbol::PinPoint pinPoint;
                            pinPoint.point31 = computedPinPoint.point31;
                            pinPoint.basePathPointIndex = computedPinPoint.basePathPointIndex;
                            pinPoint.offsetFromBasePathPoint31 = computedPinPoint.offsetFromBasePathPoint31;
                            pinPoint.normalizedOffsetFromBasePathPoint = computedPinPoint.normalizedOffsetFromBasePathPoint;

                            const auto onPathSymbolInstance = new MapSymbolsGroup::AdditionalOnPathSymbolInstanceParameters(additionalGroupInstance.get());
                            onPathSymbolInstance->overridesPinPointOnPath = true;
                            onPathSymbolInstance->pinPointOnPath = pinPoint;
                            additionalSymbolInstance.reset(onPathSymbolInstance);
                        }

                        if (additionalSymbolInstance)
                            additionalGroupInstance->symbols.insert(symbol, qMove(additionalSymbolInstance));
                    }

                    group->additionalInstances.push_back(qMove(additionalGroupInstance));
                }
            }

            // This group needs intersection check inside group
            group->intersectionProcessingMode |= MapSymbolsGroup::IntersectionProcessingModeFlag::CheckIntersectionsWithinGroup;

            // Finally there's no need in original, so turn it off
            group->additionalInstancesDiscardOriginal = true;
        }

        // Configure group
        if (!group->symbols.isEmpty())
        {
            if (hasAtLeastOneSimpleBillboard && !(hasAtLeastOneOnPath || hasAtLeastOneAlongPathBillboard))
            {
                group->presentationMode |= MapSymbolsGroup::PresentationModeFlag::ShowNoneIfIconIsNotShown;
                group->presentationMode |= MapSymbolsGroup::PresentationModeFlag::ShowAnythingUntilFirstGap;
            }
            else if (!hasAtLeastOneSimpleBillboard && (hasAtLeastOneOnPath || hasAtLeastOneAlongPathBillboard))
            {
                group->presentationMode |= MapSymbolsGroup::PresentationModeFlag::ShowAnything;
            }
            else
            {
                LogPrintf(LogSeverityLevel::Error,
                    "%s produced incompatible set of map symbols to compute presentation mode",
                    qPrintable(group->toString()));
                group->presentationMode |= MapSymbolsGroup::PresentationModeFlag::ShowAnything;
            }
        }

        // Add constructed group to output
        symbolsGroups.push_back(qMove(group));
    }

    // Create output tile
    outTiledData.reset(new MapObjectsSymbolsProvider::Data(
        tileId,
        zoom,
        symbolsGroups,
        primitivesTile,
        new RetainableCacheMetadata(primitivesTile->retainableCacheMetadata)));

    return true;
}