ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
misc.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #include "util/misc.h"
33 
34 #include <cstdarg>
35 
36 #include <boost/algorithm/string.hpp>
37 
38 namespace colmap {
39 
40 std::string EnsureTrailingSlash(const std::string& str) {
41  if (str.length() > 0) {
42  if (str.back() != '/') {
43  return str + "/";
44  }
45  } else {
46  return str + "/";
47  }
48  return str;
49 }
50 
51 bool HasFileExtension(const std::string& file_name, const std::string& ext) {
52  CHECK(!ext.empty());
53  CHECK_EQ(ext.at(0), '.');
54  std::string ext_lower = ext;
55  StringToLower(&ext_lower);
56  if (file_name.size() >= ext_lower.size() &&
57  file_name.substr(file_name.size() - ext_lower.size(), ext_lower.size()) ==
58  ext_lower) {
59  return true;
60  }
61  return false;
62 }
63 
64 void SplitFileExtension(const std::string& path, std::string* root,
65  std::string* ext) {
66  const auto parts = StringSplit(path, ".");
67  CHECK_GT(parts.size(), 0);
68  if (parts.size() == 1) {
69  *root = parts[0];
70  *ext = "";
71  } else {
72  *root = "";
73  for (size_t i = 0; i < parts.size() - 1; ++i) {
74  *root += parts[i] + ".";
75  }
76  *root = root->substr(0, root->length() - 1);
77  if (parts.back() == "") {
78  *ext = "";
79  } else {
80  *ext = "." + parts.back();
81  }
82  }
83 }
84 
85 void FileCopy(const std::string& src_path, const std::string& dst_path,
86  CopyType type) {
87  switch (type) {
88  case CopyType::COPY:
89  boost::filesystem::copy_file(src_path, dst_path);
90  break;
92  boost::filesystem::create_hard_link(src_path, dst_path);
93  break;
95  boost::filesystem::create_symlink(src_path, dst_path);
96  break;
97  }
98 }
99 
100 bool ExistsFile(const std::string& path) {
101  return boost::filesystem::is_regular_file(path);
102 }
103 
104 bool ExistsDir(const std::string& path) {
105  return boost::filesystem::is_directory(path);
106 }
107 
108 bool ExistsPath(const std::string& path) {
109  return boost::filesystem::exists(path);
110 }
111 
112 void CreateDirIfNotExists(const std::string& path) {
113  if (!ExistsDir(path)) {
114  CHECK(boost::filesystem::create_directory(path));
115  }
116 }
117 
118 std::string GetPathBaseName(const std::string& path) {
119  const std::vector<std::string> names =
120  StringSplit(StringReplace(path, "\\", "/"), "/");
121  if (names.size() > 1 && names.back() == "") {
122  return names[names.size() - 2];
123  } else {
124  return names.back();
125  }
126 }
127 
128 std::string GetParentDir(const std::string& path) {
129  return boost::filesystem::path(path).parent_path().string();
130 }
131 
132 std::string GetRelativePath(const std::string& from, const std::string& to) {
133  // This implementation is adapted from:
134  // https://stackoverflow.com/questions/10167382
135  // A native implementation in boost::filesystem is only available starting
136  // from boost version 1.60.
137  using namespace boost::filesystem;
138 
139  path from_path = canonical(path(from));
140  path to_path = canonical(path(to));
141 
142  // Start at the root path and while they are the same then do nothing then
143  // when they first diverge take the entire from path, swap it with '..'
144  // segments, and then append the remainder of the to path.
145  path::const_iterator from_iter = from_path.begin();
146  path::const_iterator to_iter = to_path.begin();
147 
148  // Loop through both while they are the same to find nearest common directory
149  while (from_iter != from_path.end() && to_iter != to_path.end() &&
150  (*to_iter) == (*from_iter)) {
151  ++to_iter;
152  ++from_iter;
153  }
154 
155  // Replace from path segments with '..' (from => nearest common directory)
156  path rel_path;
157  while (from_iter != from_path.end()) {
158  rel_path /= "..";
159  ++from_iter;
160  }
161 
162  // Append the remainder of the to path (nearest common directory => to)
163  while (to_iter != to_path.end()) {
164  rel_path /= *to_iter;
165  ++to_iter;
166  }
167 
168  return rel_path.string();
169 }
170 
171 std::vector<std::string> GetFileList(const std::string& path) {
172  std::vector<std::string> file_list;
173  for (auto it = boost::filesystem::directory_iterator(path);
174  it != boost::filesystem::directory_iterator(); ++it) {
175  if (boost::filesystem::is_regular_file(*it)) {
176  const boost::filesystem::path file_path = *it;
177  file_list.push_back(file_path.string());
178  }
179  }
180  return file_list;
181 }
182 
183 std::vector<std::string> GetRecursiveFileList(const std::string& path) {
184  std::vector<std::string> file_list;
185  for (auto it = boost::filesystem::recursive_directory_iterator(path);
186  it != boost::filesystem::recursive_directory_iterator(); ++it) {
187  if (boost::filesystem::is_regular_file(*it)) {
188  const boost::filesystem::path file_path = *it;
189  file_list.push_back(file_path.string());
190  }
191  }
192  return file_list;
193 }
194 
195 std::vector<std::string> GetDirList(const std::string& path) {
196  std::vector<std::string> dir_list;
197  for (auto it = boost::filesystem::directory_iterator(path);
198  it != boost::filesystem::directory_iterator(); ++it) {
199  if (boost::filesystem::is_directory(*it)) {
200  const boost::filesystem::path dir_path = *it;
201  dir_list.push_back(dir_path.string());
202  }
203  }
204  return dir_list;
205 }
206 
207 std::vector<std::string> GetRecursiveDirList(const std::string& path) {
208  std::vector<std::string> dir_list;
209  for (auto it = boost::filesystem::recursive_directory_iterator(path);
210  it != boost::filesystem::recursive_directory_iterator(); ++it) {
211  if (boost::filesystem::is_directory(*it)) {
212  const boost::filesystem::path dir_path = *it;
213  dir_list.push_back(dir_path.string());
214  }
215  }
216  return dir_list;
217 }
218 
219 size_t GetFileSize(const std::string& path) {
220  std::ifstream file(path, std::ifstream::ate | std::ifstream::binary);
221  CHECK(file.is_open()) << path;
222  return file.tellg();
223 }
224 
225 void PrintHeading1(const std::string& heading) {
226  std::cout << std::endl << std::string(78, '=') << std::endl;
227  std::cout << heading << std::endl;
228  std::cout << std::string(78, '=') << std::endl << std::endl;
229 }
230 
231 void PrintHeading2(const std::string& heading) {
232  std::cout << std::endl << heading << std::endl;
233  std::cout << std::string(std::min<int>(heading.size(), 78), '-') << std::endl;
234 }
235 
236 template <>
237 std::vector<std::string> CSVToVector(const std::string& csv) {
238  auto elems = StringSplit(csv, ",;");
239  std::vector<std::string> values;
240  values.reserve(elems.size());
241  for (auto& elem : elems) {
242  StringTrim(&elem);
243  if (elem.empty()) {
244  continue;
245  }
246  values.push_back(elem);
247  }
248  return values;
249 }
250 
251 template <>
252 std::vector<int> CSVToVector(const std::string& csv) {
253  auto elems = StringSplit(csv, ",;");
254  std::vector<int> values;
255  values.reserve(elems.size());
256  for (auto& elem : elems) {
257  StringTrim(&elem);
258  if (elem.empty()) {
259  continue;
260  }
261  try {
262  values.push_back(std::stoi(elem));
263  } catch (const std::invalid_argument&) {
264  return std::vector<int>(0);
265  }
266  }
267  return values;
268 }
269 
270 template <>
271 std::vector<float> CSVToVector(const std::string& csv) {
272  auto elems = StringSplit(csv, ",;");
273  std::vector<float> values;
274  values.reserve(elems.size());
275  for (auto& elem : elems) {
276  StringTrim(&elem);
277  if (elem.empty()) {
278  continue;
279  }
280  try {
281  values.push_back(std::stod(elem));
282  } catch (const std::invalid_argument&) {
283  return std::vector<float>(0);
284  }
285  }
286  return values;
287 }
288 
289 template <>
290 std::vector<double> CSVToVector(const std::string& csv) {
291  auto elems = StringSplit(csv, ",;");
292  std::vector<double> values;
293  values.reserve(elems.size());
294  for (auto& elem : elems) {
295  StringTrim(&elem);
296  if (elem.empty()) {
297  continue;
298  }
299  try {
300  values.push_back(std::stold(elem));
301  } catch (const std::invalid_argument&) {
302  return std::vector<double>(0);
303  }
304  }
305  return values;
306 }
307 
308 std::vector<std::string> ReadTextFileLines(const std::string& path) {
309  std::ifstream file(path);
310  CHECK(file.is_open()) << path;
311 
312  std::string line;
313  std::vector<std::string> lines;
314  while (std::getline(file, line)) {
315  StringTrim(&line);
316 
317  if (line.empty()) {
318  continue;
319  }
320 
321  lines.push_back(line);
322  }
323 
324  return lines;
325 }
326 
327 void RemoveCommandLineArgument(const std::string& arg, int* argc, char** argv) {
328  for (int i = 0; i < *argc; ++i) {
329  if (argv[i] == arg) {
330  for (int j = i + 1; j < *argc; ++j) {
331  argv[i] = argv[j];
332  }
333  *argc -= 1;
334  break;
335  }
336  }
337 }
338 
339 } // namespace colmap
char type
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
static const std::string path
Definition: PointCloud.cpp:59
CopyType
Definition: misc.h:27
size_t GetFileSize(const std::string &path)
Definition: misc.cc:219
void PrintHeading2(const std::string &heading)
Definition: misc.cc:231
bool ExistsPath(const std::string &path)
Definition: misc.cc:108
void StringTrim(std::string *str)
Definition: string.cc:188
bool HasFileExtension(const std::string &file_name, const std::string &ext)
Definition: misc.cc:51
std::vector< std::string > GetRecursiveFileList(const std::string &path)
Definition: misc.cc:183
std::vector< std::string > CSVToVector(const std::string &csv)
Definition: misc.cc:237
std::string StringReplace(const std::string &str, const std::string &old_str, const std::string &new_str)
Definition: string.cc:140
std::string GetPathBaseName(const std::string &path)
Definition: misc.cc:118
void StringToLower(std::string *str)
Definition: string.cc:193
std::string GetRelativePath(const std::string &from, const std::string &to)
Definition: misc.cc:132
void SplitFileExtension(const std::string &path, std::string *root, std::string *ext)
Definition: misc.cc:64
std::vector< std::string > ReadTextFileLines(const std::string &path)
Definition: misc.cc:308
bool ExistsDir(const std::string &path)
Definition: misc.cc:104
bool ExistsFile(const std::string &path)
Definition: misc.cc:100
void CreateDirIfNotExists(const std::string &path)
Definition: misc.cc:112
std::string EnsureTrailingSlash(const std::string &str)
Definition: misc.cc:40
void PrintHeading1(const std::string &heading)
Definition: misc.cc:225
std::vector< std::string > StringSplit(const std::string &str, const std::string &delim)
Definition: string.cc:166
std::vector< std::string > GetRecursiveDirList(const std::string &path)
Definition: misc.cc:207
std::vector< std::string > GetFileList(const std::string &path)
Definition: misc.cc:171
std::string GetParentDir(const std::string &path)
Definition: misc.cc:128
void RemoveCommandLineArgument(const std::string &arg, int *argc, char **argv)
Definition: misc.cc:327
std::vector< std::string > GetDirList(const std::string &path)
Definition: misc.cc:195
void FileCopy(const std::string &src_path, const std::string &dst_path, CopyType type)
Definition: misc.cc:85