package ika.app;
import com.sanityinc.jargs.CmdLineParser;
import com.sanityinc.jargs.CmdLineParser.IllegalOptionValueException;
import com.sanityinc.jargs.CmdLineParser.Option;
import ika.geo.GeoGrid;
import ika.geo.grid.TerrainSculptorFilter;
import ika.geoexport.ESRIASCIIGridExporter;
import ika.geoimport.ESRIASCIIGridReader;
import ika.gui.*;
import ika.utils.ErrorDialog;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Main entry point.
*
* Command line option contributed by Adrian Weber, University of Bern.
*
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich
* @author Adrian Weber, Centre for Development and Environment, University of
* Bern
*/
public class Main {
/**
* Start the GUI version of Terrain Sculptor in a separate JVM to maximize
* the available heap memory space.
*/
private static void launchGUIProcess() throws IOException {
String className = MainGUI.class.getName();
String xDockAppName = ApplicationInfo.getApplicationName();
ProcessLauncher processLauncher = new ProcessLauncher();
String xDockIconPath = processLauncher.findXDockIconPath("icon.icns");
processLauncher.startJVM(className, xDockAppName, xDockIconPath);
}
/**
* A ProgressIndicator implementation which sends messages to the standard
* output.
*/
private static class CmdLineProgress implements ProgressIndicator {
private boolean aborted = false;
private int tasksCount = 0;
@Override
public void start() {
}
@Override
public void abort() {
this.aborted = true;
}
@Override
public void complete() {
}
@Override
public boolean progress(int percentage) {
System.out.print(percentage + "%\r");
return true;
}
@Override
public boolean isAborted() {
return this.aborted;
}
@Override
public void disableCancel() {
}
@Override
public void enableCancel() {
}
@Override
public void setMessage(String msg) {
System.out.println(msg);
}
@Override
public void setTotalTasksCount(int tasksCount) {
this.tasksCount = tasksCount;
}
@Override
public int getTotalTasksCount() {
return this.tasksCount;
}
@Override
public void nextTask() {
}
@Override
public int currentTask() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
/**
* Prints how to use TerrainSculptor from the command line.
*/
private static void printUsage() {
System.err.println(
"Usage: TerrainSculptor [--detail int (0 < int < 50)]\n"
+ " [--lowlandmountain int (0 < int < 45)]\n"
+ " [--valleysremoval int (0 < int < 20)]\n"
+ " [--valleydepth int (0 < int < 500)]\n"
+ " [--valleywidth int (0 < int < 100)]\n"
+ " [--ridgesremoval int (0 < int < 20)]\n"
+ " [--ridgesexaggeration int (110 < int < 2000)]\n"
+ " [--ridgessharpness int (0 < int < 150)]\n"
+ " src_dem dst_dem");
}
/**
* An command line option that expects an integer value within a defined
* range.
*/
public static class IntegerRangeOption extends Option.IntegerOption {
private final int minValue;
private final int maxValue;
private final int defaultValue;
/**
*
* @param longForm
* @param minValue Minimal accepted value
* @param maxValue Maximal accepted value
* @param defaultValue The default value
*/
public IntegerRangeOption(String longForm, int minValue, int maxValue, int defaultValue) {
super(longForm);
this.minValue = minValue;
this.maxValue = maxValue;
this.defaultValue = defaultValue;
}
@Override
protected Integer parseValue(String arg, java.util.Locale locale)
throws IllegalOptionValueException {
// Return the default value is argument is not set
if (arg == null) {
return this.defaultValue;
}
int value;
// Try to parse the argument
try {
value = Integer.parseInt(arg);
} catch (java.lang.NumberFormatException e) {
throw new IllegalOptionValueException(this, arg);
}
// Check if the values is within the set range
if (value < this.minValue || value > this.maxValue) {
throw new IllegalOptionValueException(this, arg);
}
return value;
}
@Override
public Integer getDefaultValue() {
return this.defaultValue;
}
}
/**
* main routine for the application.
*
* @param args the command line arguments
*/
public static void main(String args[]) {
// Create a new command line parser
CmdLineParser parser = new CmdLineParser();
// Add all different options from the advanced interface.
// Minimum, maximum and default values come from initComponents method
// in TerrainSculptorWindow class
IntegerRangeOption gridFilterLoopsOption = new IntegerRangeOption("detail", 0, 50, 10);
parser.addOption(gridFilterLoopsOption);
IntegerRangeOption combinationSlopeThresholdOption = new IntegerRangeOption("lowlandmountain", 0, 45, 15);
parser.addOption(combinationSlopeThresholdOption);
IntegerRangeOption valleysMeanFilterLoopsOption = new IntegerRangeOption("valleysremoval", 0, 20, 5);
parser.addOption(valleysMeanFilterLoopsOption);
IntegerRangeOption valleysExaggerationOption = new IntegerRangeOption("valleydepth", 0, 500, 40);
parser.addOption(valleysExaggerationOption);
IntegerRangeOption valleysCurvatureThresholdOption = new IntegerRangeOption("valleywidth", 0, 100, 50);
parser.addOption(valleysCurvatureThresholdOption);
IntegerRangeOption ridgesMeanFilterLoopsOption = new IntegerRangeOption("ridgesremoval", 0, 20, 5);
parser.addOption(ridgesMeanFilterLoopsOption);
IntegerRangeOption ridgesExaggerationOption = new IntegerRangeOption("ridgesexaggeration", 110, 2000, 500);
parser.addOption(ridgesExaggerationOption);
IntegerRangeOption planCurvatureWeightOption = new IntegerRangeOption("ridgessharpness", 0, 150, 150);
parser.addOption(planCurvatureWeightOption);
// Add a help option which prints the usage
Option<Boolean> help = parser.addBooleanOption('h', "help");
// Try to parse the arguments
try {
parser.parse(args);
} catch (CmdLineParser.OptionException e) {
System.err.println(e.getMessage());
printUsage();
System.exit(2);
}
// Print the usage statement if the help option is set
if (parser.getOptionValue(help, false)) {
printUsage();
System.exit(0);
}
List inputArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
boolean isDebug = inputArgs.contains("-Xdebug");
// Get the remaining arguments.
String[] remainingArgs = parser.getRemainingArgs();
// If neither a source nor a destination elevation model is set, start
// the GUI application.
if (remainingArgs.length != 2) {
// when in debug mode, directly call main method for GUI version
// otherwise launch it in a new process to maximize heap space.
if (isDebug) {
MainGUI.main(args);
} else {
try {
launchGUIProcess();
System.exit(0);
} catch (IOException ex) {
MainGUI.main(args);
}
}
} else {
// In other cases start the application in batch mode with the arguments
// set on the command line.
CmdLineProgress p = new CmdLineProgress();
// Create a new grid filter
TerrainSculptorFilter gridFilter = new TerrainSculptorFilter();
// Get paths to input and output elevation model
String inputFilePath = remainingArgs[0];
String outputFilePath = remainingArgs[1];
try {
// Read the input grid
p.setMessage("Reading grid");
GeoGrid grid = ESRIASCIIGridReader.read(inputFilePath, p);
// Add it to the grid filter
gridFilter.setGrid(grid);
// Set all grid filter options. This is analog to readGUI()
// in class TerrainSculptorWindow
gridFilter.setGridFilterLoops(parser.getOptionValue(
gridFilterLoopsOption,
gridFilterLoopsOption.getDefaultValue()));
gridFilter.setValleysMeanFilterLoops(parser.getOptionValue(
valleysMeanFilterLoopsOption,
valleysMeanFilterLoopsOption.getDefaultValue()));
gridFilter.setValleysExaggeration(parser.getOptionValue(
valleysExaggerationOption,
valleysExaggerationOption.getDefaultValue()) / 100f);
gridFilter.setValleysCurvatureUpperLimit(parser.getOptionValue(
valleysCurvatureThresholdOption,
valleysCurvatureThresholdOption.getDefaultValue()) / 100f);
gridFilter.setRidgesMeanFilterLoops(parser.getOptionValue(
ridgesMeanFilterLoopsOption,
ridgesMeanFilterLoopsOption.getDefaultValue()));
gridFilter.setRidgesExaggeration(parser.getOptionValue(
ridgesExaggerationOption,
ridgesExaggerationOption.getDefaultValue()) / 100f);
gridFilter.setCombinationSlopeThreshold(parser.getOptionValue(
combinationSlopeThresholdOption,
combinationSlopeThresholdOption.getDefaultValue()));
gridFilter.setRidgesPlancurvatureWeight(parser.getOptionValue(
planCurvatureWeightOption,
planCurvatureWeightOption.getDefaultValue()) / 100f);
// and filter the input grid
java.util.ArrayList<GeoGrid> grids = gridFilter.filter(p);
// Get the resulting filtered grid and save it to the output path
for (GeoGrid currentGrid : grids) {
if (currentGrid.getName().equals("Result")) {
p.setMessage("Exporting grid");
ESRIASCIIGridExporter.export(currentGrid, outputFilePath);
System.exit(0);
}
}
} catch (java.io.IOException e) {
System.err.println(e.getMessage());
System.exit(2);
}
}
}
}