I have an application that can import terrain data in an XYZ text format where X = latitude, Y = longitude and Z = elevation.
I am trying to convert a LiDAR .las file to this format using las2las.
I use las2las
to convert the .las file and then read the converted .las file in Python using laspy
to read the XYZ values. The X and Y values do not reflect the proper latitude/longitude of the area that the LiDAR file contains.
To illustrate, here is the .xml from the LiDAR file showing metadata, note that latitude around 46.XXXXXXXX and Longitude -96.XXXXXXX (which is what I expect):
<?xml version="1.0" standalone="yes"?>
<Metadata>
<EntityID>IWI_RedRiver-C_2008_000723</EntityID>
<ProjectName>IWI_RedRiver-C_2008</ProjectName>
<ProjectMetadataFiles>http://dds.cr.usgs.gov/lidar_v2/ND-MN/2008/IWI_RedRiver-C_2008/metadata/IWI_RedRiver-C_2008_metadata.zip</ProjectMetadataFiles>
<State>ND-MN</State>
<BeginDate>2008-04-21</BeginDate>
<EndDate>2008-05-16</EndDate>
<VerticalDatum>NAVD88</VerticalDatum>
<MapProjection>UTM</MapProjection>
<MapZone>14</MapZone>
<MapProjectionDefinition>PROJCS["NAD_1983_UTM_Zone_14N",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-99.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG",26914]]</MapProjectionDefinition>
<CenterLat>46.8520722</CenterLat>
<CenterLon>-96.8356110</CenterLon>
<ULLat>46.8613222</ULLat>
<ULLon>-96.8483721</ULLon>
<URLat>46.8608250</URLat>
<URLon>-96.8221249</URLon>
<LRLat>46.8428221</LRLat>
<LRLon>-96.8228554</LRLon>
<LLLat>46.8433194</LLLat>
<LLLon>-96.8490916</LLLon>
<MinX>664000.000</MinX>
<MaxX>665999.990</MaxX>
<MinY>5189999.998</MinY>
<MaxY>5191999.989</MaxY>
<MinZ>253.551</MinZ>
<MaxZ>330.992</MaxZ>
<VendorID>IWI_RedRiver-C_2008_R06645190</VendorID>
<NumOfPulseRecords>2559425</NumOfPulseRecords>
<NumOfPulsesByReturn>(1) 2424977 (2) 129573 (3) 4807 (4) 68</NumOfPulsesByReturn>
<NumOfPtRecords>2559425</NumOfPtRecords>
<NumOfPtsByReturn>(1) 2491531 (2) 66447 (3) 1442 (4) 5</NumOfPtsByReturn>
<Intensity>0,255</Intensity>
<NominalPulseSpacing>1.28432</NominalPulseSpacing>
<PulseDensity>0.60625</PulseDensity>
<PulseDensityNPSUnits>METER</PulseDensityNPSUnits>
<VendorNominalPulseSpacing>1.7</VendorNominalPulseSpacing>
<VendorPointDensity>.35</VendorPointDensity>
<VendorPointDensityNPSUnits>METER</VendorPointDensityNPSUnits>
<FileFormat>las</FileFormat>
<LASVersion>1.0</LASVersion>
</Metadata>
The LiDAR file I am trying to get lat/long from is called IWI_RedRiver-C_2008_000723.las so I run las2las
with these parameters:
las2las -i c:\terrainfiles\lidar\IWI_RedRiver-C_2008_000723.las -o out.las -utm 14N -target_latlong
I get XYZ values in this range:
X,Y,Z: 8433152 -8240716 27584
It is not close to what I'm expecting from the .xml file (which is the correct lat/lon).
Am I using las2las
wrong? I have tried other las2las
params such as -epsg 26914, and -sp83 ND_S and I get different X,Y,Z values but still off.
For Example:
las2las -i c:\terrainfiles\lidar\IWI_RedRiver-C_2008_000723.las -o out.las -utm 14N -sp83 ND_S -target_latlong
produces :
X,Y,Z: 4590852 505294 27624
I see las2txt
appears to do what I want from my Python script but it gives a completely different outcome as well. If I run it on the previous output of las2las
with this command:
las2txt -parse xyz -i out.las -o out.xyz
I get output that looks like this:
86.4590852 -94.9494706 276.24
86.4590849 -94.9492982 276.24
86.4590847 -94.9491291 276.32
86.4590845 -94.9489549 276.24
86.4590842 -94.9487867 276.28
86.4590869 -94.9489067 284.62
86.4590894 -94.9488187 276.20
Is there a better way to convert LiDAR .las to XYZ where X and Y are latitude/longitude values?
Best Answer
I didn't expect that this would be the answer, but it turns out that
las2las
uses the UTM latitude band letters rather than the hemisphere 'N' (North) or 'S' (South) letters with the zone number. While not stated directly, I found an example in this help pageHere's an example from that page:
Note the '-utm 17T'. The 'R', 'S', and 'T' bands are solidly in the contiguous United States (AKA lower 48). You can check out Wikipedia for more information on the latitude bands.
In this particular case, instead of using 14N, try using 14T.