1/*
2 * Copyright (c) 2014-2023 National Technology and Engineering
3 * Solutions of Sandia, LLC. Under the terms of Contract DE-NA0003525
4 * with National Technology and Engineering Solutions of Sandia, LLC,
5 * the U.S. Government retains certain rights in this software.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <tracktable/CommandLineFactories/AssemblerFromCommandLine.h>
32#include <tracktable/CommandLineFactories/PointReaderFromCommandLine.h>
33#include <tracktable/Domain/Terrestrial.h>
34#include <tracktable/RW/TrajectoryWriter.h>
35
36using TrajectoryT = tracktable::domain::terrestrial::trajectory_type;
37using PointT = typename TrajectoryT::point_type;
38using PointReaderT = tracktable::PointReader<PointT>;
39using PointReaderIteratorT = typename PointReaderT::iterator;
40using AssemblerT = tracktable::AssembleTrajectories<TrajectoryT, PointReaderIteratorT>;
41
42static constexpr auto helpmsg = R"(
43--------------------------------------------------------------------------------
44The reduce example demonstrates:
45 - Using command line factories to read points and assemble trajectories
46 - using tracktable::simplify to remove unnecessary points
47 - Writing trajectories to file for later use
48
49Typical use:
50 ./reduce --tolerance=0.00001 --input=/data/flights.tsv --output=/data/reduced.traj
51
52Defaults assume a tab separated file formatted as :
53
54OBJECTID TIMESTAMP LON LAT
55
56Default output is standard out
57--------------------------------------------------------------------------------)";
58
59int main(int _argc, char* _argv[]) {
60 // Set log level to reduce unecessary output
61 tracktable::set_log_level(tracktable::log::info);
62 // Create a basic command line option with boost
63 boost::program_options::options_description commandLineOptions("Options");
64 double tolerance = 0.00001;
65 // clang-format off
66 commandLineOptions.add_options()
67 ("help", "Print help")
68 ;
69 // clang-format on
70 // Create command line factories
71 tracktable::PointReaderFromCommandLine<PointT> readerFactory;
72 tracktable::AssemblerFromCommandLine<TrajectoryT> assemblerFactory;
73 // Add options from the factories
74 readerFactory.addOptions(commandLineOptions);
75 assemblerFactory.addOptions(commandLineOptions);
76
77 // And a command line option for output
78 // clang-format off
79 commandLineOptions.add_options()
80 ("output", bpo::value<std::string>()->default_value("-"),
81 "file to write to (use '-' for stdout)")
82 ("tolerance", bpo::value<double>(&tolerance)->default_value(0.00001),
83 "Tolerance for the simplify routine");
84 // clang-format on
85
86 /** Boost program options using a variable map to tie everything together.
87 * one parse will have a single variable map. We need to let the factories know
88 * about this variable map so they can pull information out of it */
89 auto vm = std::make_shared<boost::program_options::variables_map>();
90 readerFactory.setVariables(vm);
91 assemblerFactory.setVariables(vm);
92
93 // Parse the command lines, don't forget the 'notify' after
94 try {
95 // We use this try/catch to automatically display help when an unknown option is used
96 boost::program_options::store(
97 boost::program_options::command_line_parser(_argc, _argv).options(commandLineOptions).run(), *vm);
98 boost::program_options::notify(*vm);
99 } catch (boost::program_options::error e) {
100 std::cerr << e.what();
101 std::cerr << helpmsg << "\n\n";
102 std::cerr << commandLineOptions << std::endl;
103 return 1;
104 }
105 /** Parsing will give an error of an incorrect option is used, but it won't
106 * display the help unless we tell it too */
107 if (vm->count("help") != 0) {
108 std::cerr << helpmsg << "\n\n";
109 std::cerr << commandLineOptions << std::endl;
110 return 1;
111 }
112
113 // Create Point Reader and assembler
114 auto pointReader = readerFactory.createPointReader();
115 auto assembler = assemblerFactory.createAssembler(pointReader);
116
117 // We default to standard out
118 std::ostream* o = &std::cout;
119 auto filename = (*vm)["output"].as<std::string>();
120 std::cerr << "Writing to ";
121 if ("-" != filename) {
122 // we swap in a file if a filename is specified
123 std::cerr << filename << std::endl;
124 o = new std::ofstream(filename);
125 } else {
126 std::cerr << "standard out" << std::endl;
127 }
128
129 // trajectory writer with default options
130 tracktable::TrajectoryWriter writer(*o);
131
132 auto count = 0u;
133 std::cerr << std::right;
134 // We don't need to bother storing trajectories, we can just write them
135 auto sum = 0u;
136 for (auto t = assembler->begin(); t != assembler->end(); ++t) {
137 auto s = tracktable::simplify(*t, tolerance);
138 sum += (*t).size() - s.size();
139 writer.write(s);
140 std::cerr << "\b\b\b\b\b\b\b\b\b\b" << std::setw(10) // Using backspaces for in place counter
141 << count++;
142 }
143 std::cerr << "\nRemoved " << sum << " points" << std::endl;
144 return 0;
145}