1 /******************************************************************************
2 * Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following
8 * conditions are met:
9 *
10 *     * Redistributions of source code must retain the above copyright
11 *       notice, this list of conditions and the following disclaimer.
12 *     * Redistributions in binary form must reproduce the above copyright
13 *       notice, this list of conditions and the following disclaimer in
14 *       the documentation and/or other materials provided
15 *       with the distribution.
16 *     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
17 *       names of its contributors may be used to endorse or promote
18 *       products derived from this software without specific prior
19 *       written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 * OF SUCH DAMAGE.
33 ****************************************************************************/
34 
35 #include "SplitKernel.hpp"
36 
37 #include <io/BufferReader.hpp>
38 #include <pdal/StageFactory.hpp>
39 #include <pdal/util/Utils.hpp>
40 
41 namespace pdal
42 {
43 
44 static StaticPluginInfo const s_info
45 {
46     "kernels.split",
47     "Split Kernel",
48     "http://pdal.io/apps/split.html"
49 };
50 
CREATE_STATIC_KERNEL(SplitKernel,s_info)51 CREATE_STATIC_KERNEL(SplitKernel, s_info)
52 
53 std::string SplitKernel::getName() const
54 {
55     return s_info.name;
56 }
57 
58 
addSwitches(ProgramArgs & args)59 void SplitKernel::addSwitches(ProgramArgs& args)
60 {
61     args.add("input,i", "Input filename", m_inputFile).setPositional();
62     args.add("output,o", "Output filename", m_outputFile).setPositional();
63     args.add("length", "Edge length for splitter cells", m_length, 0.0);
64     args.add("capacity", "Point capacity of chipper cells", m_capacity);
65     args.add("origin_x", "Origin in X axis for splitter cells", m_xOrigin,
66         std::numeric_limits<double>::quiet_NaN());
67     args.add("origin_y", "Origin in Y axis for splitter cells", m_yOrigin,
68         std::numeric_limits<double>::quiet_NaN());
69 }
70 
71 
validateSwitches(ProgramArgs & args)72 void SplitKernel::validateSwitches(ProgramArgs& args)
73 {
74     if (m_length && m_capacity)
75         throw pdal_error("Can't specify both length and capacity.");
76     if (!m_length && !m_capacity)
77         m_capacity = 100000;
78     if (m_outputFile.back() == Utils::dirSeparator)
79         m_outputFile += m_inputFile;
80 }
81 
82 
83 namespace
84 {
makeFilename(const std::string & s,int i)85 std::string makeFilename(const std::string& s, int i)
86 {
87     std::string out = s;
88     auto pos = out.find_last_of('.');
89     if (pos == out.npos)
90         pos = out.length();
91     out.insert(pos, std::string("_") + std::to_string(i));
92     return out;
93 }
94 }
95 
96 
execute()97 int SplitKernel::execute()
98 {
99     Stage& reader = makeReader(m_inputFile, m_driverOverride);
100 
101     Options filterOpts;
102     std::string driver = (m_length ? "filters.splitter" : "filters.chipper");
103     if (m_length)
104     {
105         filterOpts.add("length", m_length);
106         filterOpts.add("origin_x", m_xOrigin);
107         filterOpts.add("origin_y", m_yOrigin);
108     }
109     else
110     {
111         filterOpts.add("capacity", m_capacity);
112     }
113     Stage& f = makeFilter(driver, reader, filterOpts);
114 
115     ColumnPointTable table;
116     f.prepare(table);
117     PointViewSet pvSet = f.execute(table);
118 
119     int filenum = 1;
120     for (auto& pvp : pvSet)
121     {
122         BufferReader reader;
123         reader.addView(pvp);
124 
125         std::string filename = makeFilename(m_outputFile, filenum++);
126         Stage& writer = makeWriter(filename, reader, "");
127 
128         writer.prepare(table);
129         writer.execute(table);
130     }
131     return 0;
132 }
133 
134 } // namespace pdal
135