PTS to LAS format conversion problem
PTS to LAS format conversion problem
Hello everyone
I have encoutered a little problem while I tried to change the point clouds formats in CC command line mode from PTS to LAS/LAZ.
The PTS containing the following information:
X,Y,Z,Intensity
The problem is that the intensity values are imported as scalar values into a scalar field (SF). And when I save this imported PTS pointcloud as LAS the scalar values in the SF are not saved as LAS intensity values. Instead they are saved as an additional SF to the LAS and the LAS intensities are filled with zeros. So something like this:
X,Y,Z, Intensity (all 0.0), SF0 (with intensity values)
I would need the SF to be saved in the LAS as intensity instead:
X,Y,Z, Intensity (with intensity values)
I need the LAS to be saved in this way to read the LAS intensities with another tool I have.
I have found out that renaming the SF manually to "intensity" will do the trick. But this is not possible to do in command line mode.
Any help?!
I have encoutered a little problem while I tried to change the point clouds formats in CC command line mode from PTS to LAS/LAZ.
The PTS containing the following information:
X,Y,Z,Intensity
The problem is that the intensity values are imported as scalar values into a scalar field (SF). And when I save this imported PTS pointcloud as LAS the scalar values in the SF are not saved as LAS intensity values. Instead they are saved as an additional SF to the LAS and the LAS intensities are filled with zeros. So something like this:
X,Y,Z, Intensity (all 0.0), SF0 (with intensity values)
I would need the SF to be saved in the LAS as intensity instead:
X,Y,Z, Intensity (with intensity values)
I need the LAS to be saved in this way to read the LAS intensities with another tool I have.
I have found out that renaming the SF manually to "intensity" will do the trick. But this is not possible to do in command line mode.
Any help?!
Re: PTS to LAS format conversion problem
Yes, it's because LAS expect scalar fields with particular names. And your intensity SF is probably named 'Intensity' by default.
What you can do is to add a comment line at the beginning of the PTS file with the names of the columns:
This should let CC deduce the right names/roles of each column.
What you can do is to add a comment line at the beginning of the PTS file with the names of the columns:
Code: Select all
#X Y Z Intensity
Daniel, CloudCompare admin
Re: PTS to LAS format conversion problem
Thanks for your help, Daniel!
I unterstand your idea how to solve my problem. But if I would do that, I currently would have to manually insert that line into every PTS file I have. And I have usually saveral PTS files to convert at once. That's also why I would like to do the PTS to LAS format conversion with the CC command line mode.
I saw in another forum topic, that someone suggested to implement a command line function to rename scalar fields. This would be a fabulous solution for my problem, too! Don't you think?
Or, a even better solution would be to name the first scalar automatically as "intensity", when CC imports a PTS file. As far as I know the sequence "X Y Z Intensity R G B" is the defined order of the PTS format.
I unterstand your idea how to solve my problem. But if I would do that, I currently would have to manually insert that line into every PTS file I have. And I have usually saveral PTS files to convert at once. That's also why I would like to do the PTS to LAS format conversion with the CC command line mode.
I saw in another forum topic, that someone suggested to implement a command line function to rename scalar fields. This would be a fabulous solution for my problem, too! Don't you think?
Or, a even better solution would be to name the first scalar automatically as "intensity", when CC imports a PTS file. As far as I know the sequence "X Y Z Intensity R G B" is the defined order of the PTS format.
-
- Posts: 187
- Joined: Tue Mar 05, 2019 3:59 pm
Re: PTS to LAS format conversion problem
@Daniel
What would you think about when saving to LAS looking for Intensity and falling back to intensity if it exists and Intensity does not?
I know I've seen this issue pop up a few times over the years.
What would you think about when saving to LAS looking for Intensity and falling back to intensity if it exists and Intensity does not?
I know I've seen this issue pop up a few times over the years.
Re: PTS to LAS format conversion problem
Just btw.,daniel wrote: ↑Sat Feb 20, 2021 4:55 pm What you can do is to add a comment line at the beginning of the PTS file with the names of the columns:This should let CC deduce the right names/roles of each column.Code: Select all
#X Y Z Intensity
I cannot get this to work with a PTS file. Even not with a simple TXT file like this:
Code: Select all
#X Y Z Intensity
3537692.999 5151074.527 377.571 136.000
3537693.031 5151074.521 377.565 71.000
3537693.040 5151074.519 377.565 94.000
In my opinion the best way would still be to label the fourth value in a PTS file as intensity (or to load them into a SF and name the SF "Intensity"). As daniel mentioned back in 2015 (see here: http://www.danielgm.net/cc/forum/viewtopic.php?t=1307) the fourth value is defined as intensity in a PTS file. And just btw, I also heard that Leica was the first one who defined the PTS format.
Or implement the command line function to rename scalar fields. I would favour this idea, because this might become handy for other problems, too :)
@WargodHernandez
Thanks for your support. And I can imagine you are rigth, that I am not the first one who points to this issue.
But I think your solution to check for intensities at the LAS export, might lead to more problems. LAS intensities must be saved as unsigned short (0 - 65535). Scalar values or intensities from other scources (like TXT, E57) might not be in that given range. That might also be the reason why Daniel choose to save them in the LAS under additional data.
In the current version (CC 2.12) all values out of that range (0-65535) are saved as 0, if you rename the scalar field to "Intensity" before the LAS export.
Re: PTS to LAS format conversion problem
Oh, so I did a mistake, it was '//' instead of '#'.
But you are right, having a command line method to rename a scalar field would probably be the simplest solution in the end.
@Chris: the issue with auto assigning a scalar field to 'Intensity' is that LAS files have some expectations regarding intensity values (unsigned short integer). But on the other side, if the user does it on its side, I can't remember if we check the values either or if PDAL will complain if the values are outside of the specifications.
But you are right, having a command line method to rename a scalar field would probably be the simplest solution in the end.
@Chris: the issue with auto assigning a scalar field to 'Intensity' is that LAS files have some expectations regarding intensity values (unsigned short integer). But on the other side, if the user does it on its side, I can't remember if we check the values either or if PDAL will complain if the values are outside of the specifications.
Daniel, CloudCompare admin
-
- Posts: 187
- Joined: Tue Mar 05, 2019 3:59 pm
Re: PTS to LAS format conversion problem
if renaming the Scalar field doesn't solve your problem then changing its name at the time of import shouldn't fix anything, when we load something like intensity it gets loaded into a scalar field there isn't a specific Intensity field.In the current version (CC 2.12) all values out of that range (0-65535) are saved as 0, if you rename the scalar field to "Intensity" before the LAS export.
but if the range is 0-65535, we should include an option to remap the SF to that range we do something like that in the enhanceRGBWithIntensitySF function which remaps the SF to 0-255
Code: Select all
double newI = 255 * ((sf->getValue(i) - minI) / intRange); //in [0 ; 1]
Code: Select all
double intRange = maxI - minI;
-
- Posts: 187
- Joined: Tue Mar 05, 2019 3:59 pm
Re: PTS to LAS format conversion problem
@Daniel
they do not appear to check here is LASFWFFilter.cpp
and here is saving for LASFilter.cpp
It appears to use the default
they do not appear to check here is LASFWFFilter.cpp
Code: Select all
case LAS_INTENSITY:
laspoint.set_intensity(static_cast<U16>(it->sf->getValue(i)));
break;
and here is saving for LASFilter.cpp
Code: Select all
// standard las fields
uint8_t classFlags = 0;
uint8_t classification = 0;
for (const LasField &lasField: fieldsToSave)
{
assert(lasField.sf);
Id pdalId = typeToId(lasField.type, minPointFormat);
switch (lasField.type)
{
case LAS_X:
case LAS_Y:
case LAS_Z:
case LAS_RED:
case LAS_GREEN:
case LAS_BLUE:
assert(false);
break;
case LAS_TIME:
point.setField(pdalId, lasField.sf->getValue(ptsWritten) + lasField.sf->getGlobalShift());
break;
case LAS_CLASSIFICATION:
classification = static_cast<uint8_t>(static_cast<int>(lasField.sf->getValue(ptsWritten)) & 255);
break;
case LAS_CLASSIF_VALUE:
classification = static_cast<uint8_t>(static_cast<int>(lasField.sf->getValue(ptsWritten)) & (minPointFormat < 6 ? 31 : 255));
break;
case LAS_CLASSIF_SYNTHETIC:
if (lasField.sf->getValue(ptsWritten) != 0)
{
if (minPointFormat < 6)
classification |= 32; //bit #5 of the 'Classification' field
else
classFlags |= 1; //bit #0 of the 'Classification Flags' field
}
break;
case LAS_CLASSIF_KEYPOINT:
if (lasField.sf->getValue(ptsWritten) != 0)
{
if (minPointFormat < 6)
classification |= 64; //bit #6 of the 'Classification' field
else
classFlags |= 2; //bit #1 of the 'Classification Flags' field
}
break;
case LAS_CLASSIF_WITHHELD:
if (lasField.sf->getValue(ptsWritten) != 0)
{
if (minPointFormat < 6)
classification |= 128; //bit #7 of the 'Classification' field
else
classFlags |= 4; //bit #2 of the 'Classification Flags' field
}
break;
case LAS_CLASSIF_OVERLAP:
if (lasField.sf->getValue(ptsWritten) != 0)
{
if (minPointFormat >= 6)
classFlags |= 8; //bit #3 of the 'Classification Flags' field
else
assert(false);
}
break;
case LAS_INVALID:
break;
default:
point.setField(pdalId, lasField.sf->getValue(ptsWritten));
break;
}
}
-
- Posts: 187
- Joined: Tue Mar 05, 2019 3:59 pm
Re: PTS to LAS format conversion problem
@Daniel btw while looking at LASFilter.cpp I noticed the following at line #351
Shouldn't that be the logical && instead of bitwise &
Edit: Nevermind this, my local copy was outdated, you changed that in commit 31d5c1d
Code: Select all
if (hasOffsetMetaData & ccGlobalShiftManager::NeedShift(bbMax - lasOffset))
Edit: Nevermind this, my local copy was outdated, you changed that in commit 31d5c1d
Re: PTS to LAS format conversion problem
@PSpohn I've added a -RENAME_SF {sf index} {sf name} option to the command line. I'll let you test it (with the latest 2.12.alpha version online).
Daniel, CloudCompare admin