org.jgrasstools.lesto.modules.flightlines.FlightLinesIntensityNormalizer Maven / Gradle / Ivy
The newest version!
/*
* This file is part of JGrasstools (http://www.jgrasstools.org)
* (C) HydroloGIS - www.hydrologis.com
*
* JGrasstools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.jgrasstools.lesto.modules.flightlines;
import static java.lang.Math.floor;
import static java.lang.Math.pow;
import java.io.File;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.jgrasstools.gears.io.las.core.ALasReader;
import org.jgrasstools.gears.io.las.core.ALasWriter;
import org.jgrasstools.gears.io.las.core.ILasHeader;
import org.jgrasstools.gears.io.las.core.LasRecord;
import org.jgrasstools.gears.io.las.utils.GpsTimeConverter;
import org.jgrasstools.gears.io.las.utils.LasUtils;
import org.jgrasstools.gears.io.vectorreader.OmsVectorReader;
import org.jgrasstools.gears.libs.exceptions.ModelsIllegalargumentException;
import org.jgrasstools.gears.libs.modules.JGTConstants;
import org.jgrasstools.gears.libs.modules.JGTModel;
import org.jgrasstools.gears.utils.features.FeatureUtilities;
import org.jgrasstools.gears.utils.geometry.GeometryUtilities;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineSegment;
import com.vividsolutions.jts.index.strtree.STRtree;
import oms3.annotations.Author;
import oms3.annotations.Description;
import oms3.annotations.Execute;
import oms3.annotations.In;
import oms3.annotations.Keywords;
import oms3.annotations.Label;
import oms3.annotations.License;
import oms3.annotations.Name;
import oms3.annotations.Status;
import oms3.annotations.UI;
@Description("A module that normalizes flightlines based on the aircraft position.")
@Author(name = "Andrea Antonello, Silvia Franceschi", contact = "www.hydrologis.com")
@Keywords("las, normalize, flightlines")
@Label(JGTConstants.LESTO + "/flightlines")
@Name("lasflightlinesnormalization")
@Status(Status.EXPERIMENTAL)
@License(JGTConstants.GPL3_LICENSE)
public class FlightLinesIntensityNormalizer extends JGTModel {
@Description("A las file.")
@UI(JGTConstants.FILEIN_UI_HINT)
@In
public String inLas;
@Description("Shapefile containing the string fields of date, time, elev.")
@UI(JGTConstants.FILEIN_UI_HINT)
@In
public String inFlightpoints;
@Description("The square of standard range.")
@In
public double pStdRange = 600.0;
@Description("The date and time pattern (date and time field content will be concatenated through a space).")
@In
public String pDateTimePattern = "yyyy-MM-dd HH:mm:ss";
@Description("The gps time type used in the las file.")
@UI("combo:" + FlightLinesExtractor.ADJUSTED_STANDARD_GPS_TIME + "," + FlightLinesExtractor.WEEK_SECONDS_TIME)
@In
public String pGpsTimeType = FlightLinesExtractor.ADJUSTED_STANDARD_GPS_TIME;
@Description("Normalized output las file.")
@UI(JGTConstants.FILEOUT_UI_HINT)
@In
public String outLas;
@Execute
public void process() throws Exception {
checkNull(inLas, inFlightpoints, pDateTimePattern);
int timeType = -1;
if (pGpsTimeType.equals(FlightLinesExtractor.ADJUSTED_STANDARD_GPS_TIME)) {
timeType = 1;
}
if (pGpsTimeType.equals(FlightLinesExtractor.WEEK_SECONDS_TIME)) {
timeType = 0;
}
SimpleFeatureCollection flightPointsFC = OmsVectorReader.readVector(inFlightpoints);
List flightPointsList = FeatureUtilities.featureCollectionToList(flightPointsFC);
SimpleFeatureType schema = flightPointsFC.getSchema();
String dateName = FeatureUtilities.findAttributeName(schema, "date");
String timeName = FeatureUtilities.findAttributeName(schema, "time");
String elevName = FeatureUtilities.findAttributeName(schema, "elev");
if (dateName == null || timeName == null || elevName == null) {
throw new ModelsIllegalargumentException("The shapefile has to contain the fields date time and elev.", this);
}
pm.beginTask("Defining flight intervals and positions...", flightPointsList.size());
DateTimeFormatter formatter = DateTimeFormat.forPattern(pDateTimePattern).withZone(DateTimeZone.UTC);
TreeMap date2pointsMap = new TreeMap();
TreeMap points2dateMap = new TreeMap();
for( int i = 0; i < flightPointsList.size(); i++ ) {
SimpleFeature flightPoint = flightPointsList.get(i);
Geometry g1 = (Geometry) flightPoint.getDefaultGeometry();
Coordinate c1 = g1.getCoordinate();
double elev1 = ((Number) flightPoint.getAttribute(elevName)).doubleValue();
c1.z = elev1;
String date1 = flightPoint.getAttribute(dateName).toString();
String time1 = flightPoint.getAttribute(timeName).toString();
String dateTime1 = date1 + " " + time1;
DateTime d1 = formatter.parseDateTime(dateTime1);
date2pointsMap.put(d1, c1);
points2dateMap.put(c1, d1);
pm.worked(1);
}
pm.done();
pm.beginTask("Create time index...", flightPointsList.size() - 1);
DateTime minDate = null;
DateTime maxDate = null;
long minLong = Long.MAX_VALUE;
long maxLong = -Long.MAX_VALUE;
STRtree tree = new STRtree(flightPointsList.size());
Set> pointsSet = date2pointsMap.entrySet();
Entry[] array = pointsSet.toArray(new Entry[0]);
for( int i = 0; i < array.length - 1; i++ ) {
DateTime d1 = (DateTime) array[i].getKey();
Coordinate c1 = (Coordinate) array[i].getValue();
DateTime d2 = (DateTime) array[i + 1].getKey();
Coordinate c2 = (Coordinate) array[i + 1].getValue();
long millis1 = d1.getMillis();
long millis2 = d2.getMillis();
Envelope timeEnv = new Envelope(millis1, millis2, millis1, millis2);
tree.insert(timeEnv, new Coordinate[]{c1, c2});
if (millis1 < minLong) {
minLong = millis1;
minDate = d1;
}
if (millis2 > maxLong) {
maxLong = millis2;
maxDate = d2;
}
pm.worked(1);
}
pm.done();
StringBuilder sb = new StringBuilder();
sb.append("Flight data interval: ");
sb.append(minDate.toString(JGTConstants.dateTimeFormatterYYYYMMDDHHMMSS));
sb.append(" to ");
sb.append(maxDate.toString(JGTConstants.dateTimeFormatterYYYYMMDDHHMMSS));
pm.message(sb.toString());
CoordinateReferenceSystem crs = null;
File lasFile = new File(inLas);
File outLasFile = new File(outLas);
try (ALasReader reader = ALasReader.getReader(lasFile, crs); //
ALasWriter writer = ALasWriter.getWriter(outLasFile, crs);) {
reader.setOverrideGpsTimeType(timeType);
ILasHeader header = reader.getHeader();
int gpsTimeType = header.getGpsTimeType();
writer.setBounds(header);
writer.open();
pm.beginTask("Interpolating flight points and normalizing...", (int) header.getRecordsCount());
while( reader.hasNextPoint() ) {
LasRecord r = reader.getNextPoint();
DateTime gpsTimeToDateTime;
if (timeType == 0) {
gpsTimeToDateTime = GpsTimeConverter.gpsWeekTime2DateTime(r.gpsTime);
} else {
gpsTimeToDateTime = LasUtils.adjustedStandardGpsTime2DateTime(r.gpsTime);
}
long gpsMillis = gpsTimeToDateTime.getMillis();
Coordinate lasCoordinate = new Coordinate(r.x, r.y, r.z);
Envelope pEnv = new Envelope(new Coordinate(gpsMillis, gpsMillis));
List points = tree.query(pEnv);
Coordinate[] flightCoords = (Coordinate[]) points.get(0);
long d1 = points2dateMap.get(flightCoords[0]).getMillis();
long d2 = points2dateMap.get(flightCoords[1]).getMillis();
LineSegment line = new LineSegment(flightCoords[0], flightCoords[1]);
double fraction = (gpsMillis - d1) / (d2 - d1);
Coordinate interpolatedFlightPoint = line.pointAlong(fraction);
// calculate interpolated elevation
double distX = interpolatedFlightPoint.distance(flightCoords[0]);
double dist12 = flightCoords[1].distance(flightCoords[0]);
double interpolatedElev = distX / dist12 * (flightCoords[1].z - flightCoords[0].z) + flightCoords[0].z;
interpolatedFlightPoint.z = interpolatedElev;
double distanceFlightTerrain = GeometryUtilities.distance3d(lasCoordinate, interpolatedFlightPoint, null);
short norm = (short) floor(r.intensity * pow(distanceFlightTerrain, 2.0) / pStdRange + 0.5);
r.intensity = norm;
writer.addPoint(r);
pm.worked(1);
}
pm.done();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy