#include "ct_exporter_las.h" #include "private/ct_laspiecebypieceprivateexporter.h" #include "ctliblas/tools/las/ct_laspointformat0.h" #include "ctliblas/tools/las/ct_laspointformat1.h" #include "ctliblas/tools/las/ct_laspointformat2.h" #include "ctliblas/tools/las/ct_laspointformat3.h" #include "ctliblas/tools/las/ct_laspointformat4.h" #include "ctliblas/tools/las/ct_laspointformat5.h" #include "ctliblas/tools/las/ct_laspointformat6.h" #include "ctliblas/tools/las/ct_laspointformat7.h" #include "ctliblas/tools/las/ct_laspointformat8.h" #include "ctliblas/tools/las/ct_laspointformat9.h" #include "ctliblas/tools/las/ct_laspointformat10.h" CT_Exporter_LAS::CT_Exporter_LAS(int subMenuLevel) : SuperClass(subMenuLevel), mColorAttribute(nullptr), mToolsFormat(nullptr) { setCanExportPoints(true); addNewExportFormat(FileFormat("las", tr("Fichiers LAS .las"))); setToolTip(tr("Exporte tous les points au format LAS, ASPRS
http://www.asprs.org/Committee-General/LASer-LAS-File-Format-Exchange-Activities.html")); } CT_Exporter_LAS::CT_Exporter_LAS(const CT_Exporter_LAS &other) : SuperClass(other) { } QString CT_Exporter_LAS::displayableName() const { return tr("Points, LAS"); } bool CT_Exporter_LAS::setPointsToExport(const QList &list) { QList myList; QListIterator it(list); while(it.hasNext()) { CT_AbstractCloudIndex *item = it.next(); if(dynamic_cast(item) != nullptr) myList.append(item); } if(myList.isEmpty()) { setErrorMessage(errorMessage() + "\r\n" + tr("- Aucun points à exporter")); return false; } return SuperClass::setPointsToExport(myList); } void CT_Exporter_LAS::setItemsToExport(const QList& items, const QList& lasAttributesContainers) { setMustUseModels(false); clearIterators(); clearAttributesClouds(); mItems = items; for(const CT_StdLASPointsAttributesContainer* container : lasAttributesContainers) { findAttributesInContainerAndAddItToCollection(container); } } bool CT_Exporter_LAS::canExportPieceByPiece() const { return true; } CT_AbstractPieceByPieceExporter* CT_Exporter_LAS::createPieceByPieceExporter(const QString& outputFilepath) { return new CT_LASPieceByPiecePrivateExporter(*this, outputFilepath); } void CT_Exporter_LAS::internalDeclareInputModels(CT_ExporterInModelStructureManager& manager) { manager.addGroupToRootGroup(m_hInGroup); manager.addItemToGroup(m_hInGroup, m_hInItem, tr("Item à exporter")); manager.addItemToGroup(m_hInGroup, m_hInLASAttributesContainer, tr("Conteneur d'attributs LAS")); manager.addPointAttributeToGroup(m_hInGroup, m_hInReturnNumber, tr("Return Number")); manager.addPointAttributeToGroup(m_hInGroup, m_hInNumberOfReturn, tr("Number of Returns")); manager.addPointAttributeToGroup(m_hInGroup, m_hInClassificationFlag, tr("Classification Flags")); manager.addPointAttributeToGroup(m_hInGroup, m_hInScannerChannel, tr("Scanner Channel")); manager.addPointAttributeToGroup(m_hInGroup, m_hInScanDirectionFlag, tr("Scan Direction Flag")); manager.addPointAttributeToGroup(m_hInGroup, m_hInEdgeOfFlightLine, tr("Edge of Flight Line")); manager.addPointAttributeToGroup(m_hInGroup, m_hInIntensity, tr("Intensity")); manager.addPointAttributeToGroup(m_hInGroup, m_hInClassification, tr("Classification")); manager.addPointAttributeToGroup(m_hInGroup, m_hInUserData, tr("User Data")); manager.addPointAttributeToGroup(m_hInGroup, m_hInPointSourceID, tr("Point Source ")); manager.addPointAttributeToGroup(m_hInGroup, m_hInScanAngle, tr("Scan Angle")); manager.addPointAttributeToGroup(m_hInGroup, m_hInGPSTime, tr("GPS Time")); manager.addPointAttributeToGroup(m_hInGroup, m_hInRed, tr("Red")); manager.addPointAttributeToGroup(m_hInGroup, m_hInGreen, tr("Green")); manager.addPointAttributeToGroup(m_hInGroup, m_hInBlue, tr("Blue")); manager.addPointAttributeToGroup(m_hInGroup, m_hInWavePacketDescriptorIndex, tr("Wave Packet Descriptor Index")); manager.addPointAttributeToGroup(m_hInGroup, m_hInByteOffsetToWaveformData, tr("Byte Offset To Waveform Data")); manager.addPointAttributeToGroup(m_hInGroup, m_hInWaveformPacketSizeInBytes, tr("Waveform Packet Size In Bytes")); manager.addPointAttributeToGroup(m_hInGroup, m_hInReturnPointWaveformLocation, tr("Return Point Waveform Location")); manager.addPointAttributeToGroup(m_hInGroup, m_hInNIR, tr("NIR")); manager.addPointAttributeToGroup(m_hInGroup, m_hInColor, tr("Color")); } CT_AbstractExporter::ExportReturn CT_Exporter_LAS::internalExportToFile() { QList exporters; exporters << createPieceByPieceExporter(filePath()); CT_AbstractExporter::ExportReturn ret = ErrorWhenExport; if((ret = exportOnePieceOfDataToFiles(exporters)) != ErrorWhenExport) { if(!finalizePieceByPieceExport(exporters)) return ErrorWhenExport; } return ret; } CT_AbstractExporter::ExportReturn CT_Exporter_LAS::internalExportOnePiece(const QList& pieceByPieceExporters) { if(mustUseModels()) { if(mToolsFormat.isNull()) { bool atLeastOneContainer = false; for(const CT_StdLASPointsAttributesContainer* container : m_hInLASAttributesContainer.iterateInputs(m_handleResultExport)) { findAttributesInContainerAndAddItToCollection(container); atLeastOneContainer = true; } if(!atLeastOneContainer) { findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Return_Number, m_hInReturnNumber, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Number_of_Returns, m_hInNumberOfReturn, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Classification_Flags, m_hInClassificationFlag, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Scanner_Channel, m_hInScannerChannel, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Scan_Direction_Flag, m_hInScanDirectionFlag, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Edge_of_Flight_Line, m_hInEdgeOfFlightLine, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Intensity, m_hInIntensity, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Classification, m_hInClassification, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::User_Data, m_hInUserData, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Point_Source_ID, m_hInPointSourceID, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Scan_Angle_Rank, m_hInScanAngle, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::GPS_Time, m_hInGPSTime, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Red, m_hInRed, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Green, m_hInGreen, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Blue, m_hInBlue, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Wave_Packet_Descriptor_Index, m_hInWavePacketDescriptorIndex, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Byte_offset_to_waveform_data, m_hInByteOffsetToWaveformData, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Waveform_packet_size_in_bytes, m_hInWaveformPacketSizeInBytes, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::Return_Point_Waveform_Location, m_hInReturnPointWaveformLocation, mLasAttributeByType); findAttributeWithHandleAndAddItToCollection(CT_LasDefine::NIR, m_hInNIR, mLasAttributeByType); for(const CT_PointsAttributesColor* attribute : m_hInColor.iterateInputs(m_handleResultExport)) { // only use the first attribute because all other that use the same model use the same manager of attributes so there is only one cloud ! mColorAttribute = attribute; break; } } mToolsFormat.reset(createPointDataFormat()); } } else if(mToolsFormat.isNull()) { mToolsFormat.reset(createPointDataFormat()); } QList indexes; if(mustUseModels()) { if(mIteratorItemBegin == mIteratorItemEnd) { auto iterator = m_hInItem.iterateInputs(m_handleResultExport); mIteratorItemBegin = iterator.begin(); mIteratorItemEnd = iterator.end(); } int nExported = 0; const int totalToExport = maximumItemToExportInFile(std::numeric_limits::max()); while((mIteratorItemBegin != mIteratorItemEnd) && (nExported < totalToExport)) { const CT_AbstractItemDrawableWithPointCloud *item = *mIteratorItemBegin; indexes.append(item->pointCloudIndex()); ++nExported; ++mIteratorItemBegin; } } else { for(const CT_AbstractItemDrawableWithPointCloud* item : mItems) { indexes.append(item->pointCloudIndex()); } const QList &pointsSelected = pointsToExport(); QListIterator itCI(pointsSelected); while(itCI.hasNext()) { indexes.append(dynamic_cast(itCI.next())); } } QList finalPieceByPieceExporters; const quint8 pointDataFormat = getPointDataFormat(); const quint16 pointDataLength = getPointDataLength(pointDataFormat); for(CT_AbstractPieceByPieceExporter* ex : pieceByPieceExporters) { CT_LASPieceByPiecePrivateExporter* lasEx = static_cast(ex); if(lasEx->initializeHeader(pointDataFormat, pointDataLength)) finalPieceByPieceExporters.append(lasEx); } if(!finalPieceByPieceExporters.isEmpty()) { for(const CT_AbstractPointCloudIndex* index : indexes) { CT_PointIterator itP(index); while(itP.hasNext()) { const CT_Point& p = itP.next().currentPoint(); const size_t globalIndex = itP.cIndex(); auto returnNumberValues = mLasAttributeByType.value(CT_LasDefine::Return_Number); for(CT_LASPieceByPiecePrivateExporter* lasEx : finalPieceByPieceExporters) { lasEx->computePointForHeader(returnNumberValues, globalIndex, p); } } } mCurrentPieceByPieceProgress = 0; mPieceByPieceProgressMultiplicator = 1.0 / double(finalPieceByPieceExporters.size()); for(CT_LASPieceByPiecePrivateExporter* lasEx : finalPieceByPieceExporters) { connect(lasEx, &CT_LASPieceByPiecePrivateExporter::progressChanged, this, &CT_Exporter_LAS::setPieceByPieceProgress); connect(this, &CT_Exporter_LAS::mustCancel, lasEx, &CT_LASPieceByPiecePrivateExporter::cancel); lasEx->finalizeHeaderAndWritePoints(); disconnect(lasEx, nullptr, this, nullptr); disconnect(this, nullptr, lasEx, nullptr); mCurrentPieceByPieceProgress += (mPieceByPieceProgressMultiplicator * 100.0); if(isStopped()) break; } } if(mustUseModels()) return (mIteratorItemBegin == mIteratorItemEnd) ? NoMoreItemToExport : ExportCanContinue; return NoMoreItemToExport; } void CT_Exporter_LAS::clearIterators() { mIteratorItemBegin = HandleItemType::const_iterator(); mIteratorItemEnd = mIteratorItemBegin; } void CT_Exporter_LAS::clearAttributesClouds() { mLasAttributeByType.clear(); mColorAttribute = nullptr; mToolsFormat.reset(nullptr); } void CT_Exporter_LAS::findAttributesInContainerAndAddItToCollection(const CT_StdLASPointsAttributesContainer* container) { findAttributeInContainerAndAddItToCollection(CT_LasDefine::Return_Number, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Number_of_Returns, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Classification_Flags, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Scanner_Channel, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Scan_Direction_Flag, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Edge_of_Flight_Line, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Intensity, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Classification, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::User_Data, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Point_Source_ID, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Scan_Angle_Rank, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::GPS_Time, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Red, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Green, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Blue, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Wave_Packet_Descriptor_Index, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Byte_offset_to_waveform_data, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Waveform_packet_size_in_bytes, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::Return_Point_Waveform_Location, container, mLasAttributeByType); findAttributeInContainerAndAddItToCollection(CT_LasDefine::NIR, container, mLasAttributeByType); } quint8 CT_Exporter_LAS::getPointDataFormat() const { if(mLasAttributeByType.isEmpty() && (mColorAttribute == nullptr)) return 1; const QList list = mLasAttributeByType.uniqueKeys(); bool wavePacket = true; bool nir = true; bool colors = true; if(!list.contains(CT_LasDefine::Wave_Packet_Descriptor_Index) && !list.contains(CT_LasDefine::Byte_offset_to_waveform_data) && !list.contains(CT_LasDefine::Waveform_packet_size_in_bytes) && !list.contains(CT_LasDefine::Return_Point_Waveform_Location)) wavePacket = false; if(!list.contains(CT_LasDefine::NIR)) nir = false; if(!list.contains(CT_LasDefine::Red) && !list.contains(CT_LasDefine::Green) && !list.contains(CT_LasDefine::Blue) && (mColorAttribute == nullptr)) colors = false; if(wavePacket) { if(nir || colors) return 10; return 9; } if(nir) return 8; if(colors) return 7; return 1; } quint16 CT_Exporter_LAS::getPointDataLength(const int &optFormat) const { int format = optFormat; if((format < 0) || (format > 10)) format = getPointDataFormat(); if(format == 0) return quint16(CT_LASPointFormat0().sizeInBytes()); else if(format == 1) return quint16(CT_LASPointFormat1().sizeInBytes()); else if(format == 2) return quint16(CT_LASPointFormat2().sizeInBytes()); else if(format == 3) return quint16(CT_LASPointFormat3().sizeInBytes()); else if(format == 4) return quint16(CT_LASPointFormat4().sizeInBytes()); else if(format == 5) return quint16(CT_LASPointFormat5().sizeInBytes()); else if(format == 6) return quint16(CT_LASPointFormat6().sizeInBytes()); else if(format == 7) return quint16(CT_LASPointFormat7().sizeInBytes()); else if(format == 8) return quint16(CT_LASPointFormat8().sizeInBytes()); else if(format == 9) return quint16(CT_LASPointFormat9().sizeInBytes()); else if(format == 10) return quint16(CT_LASPointFormat10().sizeInBytes()); return 0; } CT_AbstractLASPointFormat* CT_Exporter_LAS::createPointDataFormat(const int &optFormat) const { int format = optFormat; if((format < 0) || (format > 10)) format = getPointDataFormat(); if(format == 0) return new CT_LASPointFormat0(); else if(format == 1) return new CT_LASPointFormat1(); else if(format == 2) return new CT_LASPointFormat2(); else if(format == 3) return new CT_LASPointFormat3(); else if(format == 4) return new CT_LASPointFormat4(); else if(format == 5) return new CT_LASPointFormat5(); else if(format == 6) return new CT_LASPointFormat6(); else if(format == 7) return new CT_LASPointFormat7(); else if(format == 8) return new CT_LASPointFormat8(); else if(format == 9) return new CT_LASPointFormat9(); else if(format == 10) return new CT_LASPointFormat10(); return nullptr; } void CT_Exporter_LAS::setPieceByPieceProgress(int progress) { const double finalProgress = double(progress) * mPieceByPieceProgressMultiplicator; setExportProgress(int(finalProgress + mCurrentPieceByPieceProgress)); }