#include "ct_reader_points_ascii.h"
#include "ct_view/tools/ct_textfileconfigurationdialog.h"
#include "ct_colorcloud/ct_colorcloudstdvector.h"
#include "ct_normalcloud/ct_normalcloudstdvector.h"
#include "ct_point.h"
#include "ct_normal.h"
#include "ct_coordinates/tools/ct_coordinatesystemmanager.h"
#include "ct_log/ct_logmanager.h"
#define CHK_ERR(argFunc, argErrStr) if(!error && !argFunc) { error = true; PS_LOG->addErrorMessage(LogInterface::reader, argErrStr); }
QString intensity_column_str = QObject::tr("Intensité");
QString red_column_str = QObject::tr("Rouge");
QString green_column_str = QObject::tr("Vert");
QString blue_column_str = QObject::tr("Bleu");
QString nx_column_str = QObject::tr("Normale X");
QString ny_column_str = QObject::tr("Normale Y");
QString nz_column_str = QObject::tr("Normale Z");
QString nw_column_str = QObject::tr("Normale Curvature");
#define X_COLUMN "X"
#define Y_COLUMN "Y"
#define Z_COLUMN "Z"
#define INTENSITY_COLUMN intensity_column_str
#define RED_COLUMN red_column_str
#define GREEN_COLUMN green_column_str
#define BLUE_COLUMN blue_column_str
#define NX_COLUMN nx_column_str
#define NY_COLUMN ny_column_str
#define NZ_COLUMN nz_column_str
#define NW_COLUMN nw_column_str
CT_Reader_Points_ASCII::CT_Reader_Points_ASCII(int subMenuLevel) : SuperClass(subMenuLevel), CT_ReaderPointsFilteringExtension()
{
m_firstConfiguration = true;
m_columnXIndex = -1;
m_columnYIndex = -1;
m_columnZIndex = -1;
m_columnIntensityIndex = -1;
m_columnRedIndex = -1;
m_columnGreenIndex = -1;
m_columnBlueIndex = -1;
m_columnNxIndex = -1;
m_columnNyIndex = -1;
m_columnNzIndex = -1;
m_columnNCurvatureIndex = -1;
m_nLinesToSkip = 0;
m_hasHeader = false;
m_separator = ".";
m_localeName = "";
addNewReadableFormat(FileFormat(QStringList() << "xyz" << "asc" << "txt" << "csv" << "ptx", tr("Fichiers ascii")));
setToolTip(tr("Chargement d'un fichier de points au format ASCII.
"
"L'import est configurable, le fichier devant contenir les champs suivants :
"
"- X : Coordonnée X du points
"
"- Y : Coordonnée Y du point
"
"- Z : Coordonnée Y du point
"
"De plus les champs suivants peuvent être fournis mais sont optionnels :
"
"- Intensité : Intensité du point
"
"- Rouge : Composante rouge du point
"
"- Vert : Composante verte du point
"
"- Bleu : Composante bleue du point
"
"- Normale X : Coordonnée Y de la normale au point
"
"- Normale Y : Coordonnée Y de la normale au point
"
"- Normale Z : Coordonnée Y de la normale au point
"));
}
CT_Reader_Points_ASCII::CT_Reader_Points_ASCII(const CT_Reader_Points_ASCII &other) : SuperClass(other), CT_ReaderPointsFilteringExtension()
{
m_firstConfiguration = other.m_firstConfiguration;
m_columnXIndex = other.m_columnXIndex;
m_columnYIndex = other.m_columnYIndex;
m_columnZIndex = other.m_columnZIndex;
m_columnIntensityIndex = other.m_columnIntensityIndex;
m_columnRedIndex = other.m_columnRedIndex;
m_columnGreenIndex = other.m_columnGreenIndex;
m_columnBlueIndex = other.m_columnBlueIndex;
m_columnNxIndex = other.m_columnNxIndex;
m_columnNyIndex = other.m_columnNyIndex;
m_columnNzIndex = other.m_columnNzIndex;
m_columnNCurvatureIndex = other.m_columnNCurvatureIndex;
m_nLinesToSkip = other.m_nLinesToSkip;
m_hasHeader = other.m_hasHeader;
m_separator = other.m_separator;
m_localeName = other.m_localeName;
}
QString CT_Reader_Points_ASCII::displayableName() const
{
return tr("Nuage de points, Fichiers ASCII (paramétrable)");
}
bool CT_Reader_Points_ASCII::configure()
{
// Columns that can be found in the ascii file
QList fieldList;
fieldList.append(CT_TextFileConfigurationFields(X_COLUMN, QRegExp(" *[xX] *"))); // x
fieldList.append(CT_TextFileConfigurationFields(Y_COLUMN, QRegExp(" *[yY] *"))); // y
fieldList.append(CT_TextFileConfigurationFields(Z_COLUMN, QRegExp(" *[zZ] *"))); // z
fieldList.append(CT_TextFileConfigurationFields(INTENSITY_COLUMN, QRegExp("[iI].*"))); // intensité - intensity - intensidad - intensität - i
fieldList.append(CT_TextFileConfigurationFields(RED_COLUMN, QRegExp("[rR].*"))); // rouge - red - rojo - rot - r
fieldList.append(CT_TextFileConfigurationFields(GREEN_COLUMN, QRegExp("[vVgG].*"))); // vert - green - verde - grün - v - g
fieldList.append(CT_TextFileConfigurationFields(BLUE_COLUMN, QRegExp("[bBaA].*"))); // bleu - blue - azul - blau - b - a
fieldList.append(CT_TextFileConfigurationFields(NX_COLUMN, QRegExp("[nN].*[xX]"))); // normale x - normal x - normali x - normalen x - nx
fieldList.append(CT_TextFileConfigurationFields(NY_COLUMN, QRegExp("[nN].*[yY]"))); // normale y - normal y - normali y - normalen y - ny
fieldList.append(CT_TextFileConfigurationFields(NZ_COLUMN, QRegExp("[nN].*[zZ]"))); // normale z - normal z - normali z - normalen z - nz
fieldList.append(CT_TextFileConfigurationFields(NW_COLUMN, QRegExp("[nN].*[wW]"))); // normale w - normal w - normali w - normalen w - nw
// a configurable dialog that help the user to select the right column and auto-detect some columns
CT_TextFileConfigurationDialog dialog(fieldList, nullptr, filepath());
dialog.setFileExtensionAccepted(readableFormats());
dialog.setFilePathCanBeModified(filePathCanBeModified());
if (QFileInfo(filepath()).suffix() == "ptx")
{
m_hasHeader = false;
m_nLinesToSkip = 6;
m_separator = " ";
dialog.setHeader(m_hasHeader);
dialog.setNLinesToSkip(m_nLinesToSkip);
dialog.setSeparator(m_separator);
}
// table that link a sought column to a column in the ascii file
QMap corresp;
// if it is not the first configuration
if(!m_firstConfiguration)
{
// we will set by default columns detected in last configuration
corresp.insert(X_COLUMN, m_columnXIndex);
corresp.insert(Y_COLUMN, m_columnYIndex);
corresp.insert(Z_COLUMN, m_columnZIndex);
corresp.insert(INTENSITY_COLUMN, m_columnIntensityIndex);
corresp.insert(RED_COLUMN, m_columnRedIndex);
corresp.insert(GREEN_COLUMN, m_columnGreenIndex);
corresp.insert(BLUE_COLUMN, m_columnBlueIndex);
corresp.insert(NX_COLUMN, m_columnNxIndex);
corresp.insert(NY_COLUMN, m_columnNyIndex);
corresp.insert(NZ_COLUMN, m_columnNzIndex);
corresp.insert(NW_COLUMN, m_columnNCurvatureIndex);
// and other elements like header, number of lines to skip, etc...
dialog.setHeader(m_hasHeader);
dialog.setNLinesToSkip(m_nLinesToSkip);
dialog.setSeparator(m_separator);
dialog.setQLocale(m_localeName);
dialog.setFieldColumnsSelected(corresp);
}
if(dialog.exec() != QDialog::Accepted)
return false;
// get the link between sought columns and column in the ascii file selected by the user
corresp = dialog.getNeededFieldColumns();
if((corresp.value(X_COLUMN, -1) < 0)
|| (corresp.value(Y_COLUMN, -1) < 0)
|| (corresp.value(Z_COLUMN, -1) < 0))
return false;
m_firstConfiguration = false;
int columnXIndex = corresp.value(X_COLUMN);
int columnYIndex = corresp.value(Y_COLUMN);
int columnZIndex = corresp.value(Z_COLUMN);
int columnIntensityIndex = corresp.value(INTENSITY_COLUMN, -1);
int columnRedIndex = corresp.value(RED_COLUMN, -1);
int columnGreenIndex = corresp.value(GREEN_COLUMN, -1);
int columnBlueIndex = corresp.value(BLUE_COLUMN, -1);
int columnNxIndex = corresp.value(NX_COLUMN, -1);
int columnNyIndex = corresp.value(NY_COLUMN, -1);
int columnNzIndex = corresp.value(NZ_COLUMN, -1);
int columnNCurvatureIndex = corresp.value(NW_COLUMN, -1);
m_columnXIndex = columnXIndex;
m_columnYIndex = columnYIndex;
m_columnZIndex = columnZIndex;
m_columnIntensityIndex = columnIntensityIndex;
m_columnRedIndex = columnRedIndex;
m_columnGreenIndex = columnGreenIndex;
m_columnBlueIndex = columnBlueIndex;
m_columnNxIndex = columnNxIndex;
m_columnNyIndex = columnNyIndex;
m_columnNzIndex = columnNzIndex;
m_columnNCurvatureIndex = columnNCurvatureIndex;
m_nLinesToSkip = dialog.getNlinesToSkip();
m_hasHeader = dialog.hasHeader();
m_separator = dialog.getSeparator();
m_localeName = dialog.getQLocaleName();
if(!filePathCanBeModified() && !filepath().isEmpty())
return true;
return setFilePath(dialog.getFileNameWithPath());
}
void CT_Reader_Points_ASCII::saveSettings(SettingsWriterInterface &writer) const
{
SuperClass::saveSettings(writer);
writer.addParameter(this, "HasHeader", m_hasHeader);
writer.addParameter(this, "NLinesToSkip", m_nLinesToSkip);
writer.addParameter(this, "Separator", m_separator);
writer.addParameter(this, "LocaleName", m_localeName);
writer.addParameter(this, "ColumnXIndex", m_columnXIndex);
writer.addParameter(this, "ColumnYIndex", m_columnYIndex);
writer.addParameter(this, "ColumnZIndex", m_columnZIndex);
writer.addParameter(this, "ColumnIntensityIndex", m_columnIntensityIndex);
writer.addParameter(this, "ColumnRedIndex", m_columnRedIndex);
writer.addParameter(this, "ColumnGreenIndex", m_columnGreenIndex);
writer.addParameter(this, "ColumnBlueIndex", m_columnBlueIndex);
writer.addParameter(this, "ColumnNxIndex", m_columnNxIndex);
writer.addParameter(this, "ColumnNyIndex", m_columnNyIndex);
writer.addParameter(this, "ColumnNzIndex", m_columnNzIndex);
writer.addParameter(this, "ColumnNCurvatureIndex", m_columnNCurvatureIndex);
}
bool CT_Reader_Points_ASCII::restoreSettings(SettingsReaderInterface &reader)
{
if(!SuperClass::restoreSettings(reader))
return false;
QVariant value;
if(reader.parameter(this, "HasHeader", value))
m_hasHeader = value.toBool();
if(reader.parameter(this, "NLinesToSkip", value))
m_nLinesToSkip = value.toInt();
if(reader.parameter(this, "Separator", value))
m_separator = value.toString();
if(reader.parameter(this, "LocaleName", value))
m_localeName = value.toString();
if(reader.parameter(this, "ColumnXIndex", value))
m_columnXIndex = value.toInt();
if(reader.parameter(this, "ColumnYIndex", value))
m_columnYIndex = value.toInt();
if(reader.parameter(this, "ColumnZIndex", value))
m_columnZIndex = value.toInt();
if(reader.parameter(this, "ColumnIntensityIndex", value))
m_columnIntensityIndex = value.toInt();
if(reader.parameter(this, "ColumnRedIndex", value))
m_columnRedIndex = value.toInt();
if(reader.parameter(this, "ColumnGreenIndex", value))
m_columnGreenIndex = value.toInt();
if(reader.parameter(this, "ColumnBlueIndex", value))
m_columnBlueIndex = value.toInt();
if(reader.parameter(this, "ColumnNxIndex", value))
m_columnNxIndex = value.toInt();
if(reader.parameter(this, "ColumnNyIndex", value))
m_columnNyIndex = value.toInt();
if(reader.parameter(this, "ColumnNzIndex", value))
m_columnNzIndex = value.toInt();
if(reader.parameter(this, "ColumnNCurvatureIndex", value))
m_columnNCurvatureIndex = value.toInt();
return true;
}
void CT_Reader_Points_ASCII::setXColumnIndex(int index)
{
m_columnXIndex = index;
}
void CT_Reader_Points_ASCII::setYColumnIndex(int index)
{
m_columnYIndex = index;
}
void CT_Reader_Points_ASCII::setZColumnIndex(int index)
{
m_columnZIndex = index;
}
void CT_Reader_Points_ASCII::setIntensityColumnIndex(int index)
{
m_columnIntensityIndex = index;
}
void CT_Reader_Points_ASCII::setRedColumnIndex(int index)
{
m_columnRedIndex = index;
}
void CT_Reader_Points_ASCII::setGreenColumnIndex(int index)
{
m_columnGreenIndex = index;
}
void CT_Reader_Points_ASCII::setBlueColumnIndex(int index)
{
m_columnBlueIndex = index;
}
void CT_Reader_Points_ASCII::setNxColumnIndex(int index)
{
m_columnNxIndex = index;
}
void CT_Reader_Points_ASCII::setNyColumnIndex(int index)
{
m_columnNyIndex = index;
}
void CT_Reader_Points_ASCII::setNzColumnIndex(int index)
{
m_columnNzIndex = index;
}
void CT_Reader_Points_ASCII::setNCurvatureIndex(int index)
{
m_columnNCurvatureIndex = index;
}
void CT_Reader_Points_ASCII::setFirstConfiguration(bool first)
{
m_firstConfiguration = first;
}
void CT_Reader_Points_ASCII::setLinesToSkip(int skip)
{
m_nLinesToSkip = skip;
}
void CT_Reader_Points_ASCII::setHasHeader(bool hasHeader)
{
m_hasHeader = hasHeader;
}
void CT_Reader_Points_ASCII::setValueSeparator(QString sep)
{
m_separator = sep;
}
void CT_Reader_Points_ASCII::setLocaleName(QString locale)
{
m_localeName = locale;
}
int CT_Reader_Points_ASCII::xColumnIndex() const
{
return m_columnXIndex;
}
int CT_Reader_Points_ASCII::yColumnIndex() const
{
return m_columnYIndex;
}
int CT_Reader_Points_ASCII::zColumnIndex() const
{
return m_columnZIndex;
}
int CT_Reader_Points_ASCII::intensityColumnIndex() const
{
return m_columnIntensityIndex;
}
int CT_Reader_Points_ASCII::redColumnIndex() const
{
return m_columnRedIndex;
}
int CT_Reader_Points_ASCII::greenColumnIndex() const
{
return m_columnGreenIndex;
}
int CT_Reader_Points_ASCII::blueColumnIndex() const
{
return m_columnBlueIndex;
}
int CT_Reader_Points_ASCII::nXColumnIndex() const
{
return m_columnNxIndex;
}
int CT_Reader_Points_ASCII::nYColumnIndex() const
{
return m_columnNyIndex;
}
int CT_Reader_Points_ASCII::nZColumnIndex() const
{
return m_columnNzIndex;
}
int CT_Reader_Points_ASCII::nCurvatureIndex() const
{
return m_columnNCurvatureIndex;
}
bool CT_Reader_Points_ASCII::canLoadPoints() const
{
return (m_columnXIndex >= 0) && (m_columnYIndex >= 0) && (m_columnZIndex >= 0);
}
bool CT_Reader_Points_ASCII::canLoadIntensity() const
{
return m_columnIntensityIndex >= 0;
}
bool CT_Reader_Points_ASCII::canLoadColors() const
{
return (m_columnRedIndex >= 0) && (m_columnGreenIndex >= 0) && (m_columnBlueIndex >= 0);
}
bool CT_Reader_Points_ASCII::canLoadNormals() const
{
return (m_columnNxIndex >= 0) && (m_columnNyIndex >= 0) && (m_columnNzIndex >= 0);
}
void CT_Reader_Points_ASCII::internalDeclareOutputModels(CT_ReaderOutModelStructureManager& manager)
{
if(canLoadPoints())
{
manager.addItem(m_outPointCloud, tr("Scène(s)"));
}
if(canLoadIntensity())
{
manager.addItem(m_outIntensity, tr("Intensités"));
}
if(canLoadColors())
{
manager.addItem(m_outColors, tr("Couleurs"));
}
if(canLoadNormals())
{
manager.addItem(m_outNormals, tr("Normales"));
}
}
bool CT_Reader_Points_ASCII::internalReadFile(CT_StandardItemGroup* group)
{
if(!canLoadPoints())
return false;
if(QFile::exists(filepath()))
{
QFile f(filepath());
if(f.open(QIODevice::ReadOnly))
{
QTextStream stream(&f);
QString currentLine;
QStringList wordsOfLine;
CT_Point point;
int nLine = 0;
int maxIndex = maxColumnIndex();
// Getting the file size to set progress
qint64 fileSize = f.size();
qint64 currentSizeRead = 0;
// create a new point cloud that size was undefined for the moment
CT_AbstractUndefinedSizePointCloud *uspc = createPointCloud();
CT_DensePointScalarManager::UPCSSetterPtr intensitySetter = createIntensityArray(uspc);
CT_DensePointColorManager::UPCSSetterPtr colorSetter = createColorsArray(uspc);
CT_DensePointNormalManager::UPCSSetterPtr normalSetter = createNormalsArray(uspc);
Eigen::Vector3d minBB, maxBB;
initBoundinBox(minBB, maxBB);
float minIntensity, maxIntensity;
minIntensity = std::numeric_limits::max();
maxIntensity = -minIntensity;
skipLines(stream, currentSizeRead);
QLocale locale(m_localeName);
bool error = false;
// While we did not reached the end of file
while(!stream.atEnd() && !isStopped() && !error) {
// Read the currentLine
++nLine;
currentLine = stream.readLine();
currentSizeRead += currentLine.size();
setProgress(int((currentSizeRead*100) / fileSize));
if(currentLine.isEmpty())
continue;
// Read each word separately
wordsOfLine = currentLine.split(m_separator, QT_SKIP_EMPTY_PARTS);
// Checking for a valid line
if(maxIndex >= wordsOfLine.size()) {
PS_LOG->addErrorMessage(LogInterface::reader, tr("Error loading at line %1: missing columns.").arg(nLine));
error = true;
}
CHK_ERR(readPoint(wordsOfLine, locale, point), tr("Error loading point at line %1").arg(nLine));
if (isPointFiltered(point))
continue;
addPoint(point, uspc, minBB, maxBB);
CHK_ERR(readAndAddIntensity(wordsOfLine, locale, intensitySetter, minIntensity, maxIntensity), tr("Error loading intensity at line %1").arg(nLine));
CHK_ERR(readAndAddColor(wordsOfLine, locale, colorSetter), tr("Error loading color at line %1").arg(nLine));
CHK_ERR(readAndAddNormal(wordsOfLine, locale, normalSetter), tr("Error loading normal at line %1").arg(nLine));
}
f.close();
CT_PCIR pcir = PS_REPOSITORY->registerUndefinedSizePointCloud(uspc);
CT_Scene* scene = new CT_Scene(pcir);
group->addSingularItem(m_outPointCloud, scene);
m_readScene = scene;
if(intensitySetter != nullptr)
group->addSingularItem(m_outIntensity, m_outIntensity.createAttributeInstance(pcir, minIntensity, maxIntensity));
if(colorSetter != nullptr)
group->addSingularItem(m_outColors, m_outColors.createAttributeInstance(pcir));
if(normalSetter != nullptr)
group->addSingularItem(m_outNormals, m_outNormals.createAttributeInstance(pcir));
return !error;
}
}
return false;
}
CT_AbstractUndefinedSizePointCloud *CT_Reader_Points_ASCII::createPointCloud() const
{
return PS_REPOSITORY->createNewUndefinedSizePointCloud();
}
CT_DensePointScalarManager::UPCSSetterPtr CT_Reader_Points_ASCII::createIntensityArray(CT_AbstractUndefinedSizePointCloud* uspc)
{
if(canLoadIntensity())
return m_outIntensity.createUndefinedPointCloudSizeAttributesSetterPtr(uspc);
return nullptr;
}
CT_DensePointColorManager::UPCSSetterPtr CT_Reader_Points_ASCII::createColorsArray(CT_AbstractUndefinedSizePointCloud* uspc)
{
if(canLoadColors())
return m_outColors.createUndefinedPointCloudSizeAttributesSetterPtr(uspc);
return nullptr;
}
CT_DensePointNormalManager::UPCSSetterPtr CT_Reader_Points_ASCII::createNormalsArray(CT_AbstractUndefinedSizePointCloud* uspc)
{
if(canLoadNormals())
return m_outNormals.createUndefinedPointCloudSizeAttributesSetterPtr(uspc);
return nullptr;
}
int CT_Reader_Points_ASCII::maxColumnIndex() const
{
int index = -1;
index = qMax(index, m_columnXIndex);
index = qMax(index, m_columnYIndex);
index = qMax(index, m_columnZIndex);
index = qMax(index, m_columnIntensityIndex);
index = qMax(index, m_columnRedIndex);
index = qMax(index, m_columnGreenIndex);
index = qMax(index, m_columnBlueIndex);
index = qMax(index, m_columnNxIndex);
index = qMax(index, m_columnNyIndex);
index = qMax(index, m_columnNzIndex);
index = qMax(index, m_columnNCurvatureIndex);
return index;
}
void CT_Reader_Points_ASCII::initBoundinBox(Eigen::Vector3d &min, Eigen::Vector3d &max) const
{
min[0] = std::numeric_limits::max();
min[1] = min[0];
min[2] = min[0];
max[0] = -min[0];
max[1] = -min[0];
max[2] = -min[0];
}
void CT_Reader_Points_ASCII::skipLines(QTextStream &stream, qint64 ¤tSizeRead) const
{
for(int i = 0 ; i < m_nLinesToSkip; ++i)
currentSizeRead += stream.readLine().size();
if (m_hasHeader)
currentSizeRead += stream.readLine().size();
}
void CT_Reader_Points_ASCII::updateBoundingBox(const CT_Point &point, Eigen::Vector3d &bboxMin, Eigen::Vector3d &bboxMax) const
{
bboxMin[0] = qMin(point[CT_Point::X], bboxMin[0]);
bboxMin[1] = qMin(point[CT_Point::Y], bboxMin[1]);
bboxMin[2] = qMin(point[CT_Point::Z], bboxMin[2]);
bboxMax[0] = qMax(point[CT_Point::X], bboxMax[0]);
bboxMax[1] = qMax(point[CT_Point::Y], bboxMax[1]);
bboxMax[2] = qMax(point[CT_Point::Z], bboxMax[2]);
}
bool CT_Reader_Points_ASCII::readPoint(const QStringList &wordsOfLine, const QLocale &locale, CT_Point &point) const
{
bool ok;
point[CT_Point::X] = locale.toDouble(wordsOfLine.at(m_columnXIndex), &ok);
if(!ok)
return false;
point[CT_Point::Y] = locale.toDouble(wordsOfLine.at(m_columnYIndex), &ok);
if(!ok)
return false;
point[CT_Point::Z] = locale.toDouble(wordsOfLine.at(m_columnZIndex), &ok);
if(!ok)
return false;
return true;
}
void CT_Reader_Points_ASCII::addPoint(const CT_Point &point,
CT_AbstractUndefinedSizePointCloud *array,
Eigen::Vector3d &minBB, Eigen::Vector3d &maxBB) const
{
array->addPoint(point);
updateBoundingBox(point, minBB, maxBB);
}
bool CT_Reader_Points_ASCII::readAndAddIntensity(const QStringList &wordsOfLine, const QLocale &locale, CT_DensePointScalarManager::UPCSSetterPtr& setter, float &minI, float &maxI) const
{
if(setter.get() == nullptr)
return true;
bool ok;
float value = locale.toFloat(wordsOfLine.at(m_columnIntensityIndex), &ok);
if(!ok)
return false;
setter->setLastValue(value);
minI = qMin(value, minI);
maxI = qMax(value, maxI);
return true;
}
bool CT_Reader_Points_ASCII::readAndAddColor(const QStringList &wordsOfLine, const QLocale &locale, CT_DensePointColorManager::UPCSSetterPtr& setter) const
{
if(setter.get() == nullptr)
return true;
bool ok;
CT_Color color;
color.r() = uchar(locale.toInt(wordsOfLine.at(m_columnRedIndex), &ok));
if(!ok)
return false;
color.g() = uchar(locale.toInt(wordsOfLine.at(m_columnGreenIndex), &ok));
if(!ok)
return false;
color.b() = uchar(locale.toInt(wordsOfLine.at(m_columnBlueIndex), &ok));
if(!ok)
return false;
setter->setLastValue(color);
return true;
}
bool CT_Reader_Points_ASCII::readAndAddNormal(const QStringList &wordsOfLine, const QLocale &locale, CT_DensePointNormalManager::UPCSSetterPtr& setter) const
{
if(setter.get() == nullptr)
return true;
bool ok;
CT_Normal normal;
normal.x() = locale.toFloat(wordsOfLine.at(m_columnNxIndex), &ok);
if(!ok)
return false;
normal.y() = locale.toFloat(wordsOfLine.at(m_columnNyIndex), &ok);
if(!ok)
return false;
normal.z() = locale.toFloat(wordsOfLine.at(m_columnNzIndex), &ok);
if(!ok)
return false;
if(m_columnNCurvatureIndex >= 0) {
normal.w() = locale.toFloat(wordsOfLine.at(m_columnNCurvatureIndex), &ok);
if(!ok)
return false;
}
setter->setLastValue(normal);
return true;
}