Panda3D
ptsToBam.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file ptsToBam.cxx
10  * @author drose
11  * @date 2000-06-28
12  */
13 
14 #include "ptsToBam.h"
15 
16 #include "config_putil.h"
17 #include "geomPoints.h"
18 #include "bamFile.h"
19 #include "pandaNode.h"
20 #include "geomNode.h"
21 #include "dcast.h"
22 #include "string_utils.h"
23 #include "config_egg2pg.h"
24 
25 using std::string;
26 
27 /**
28  *
29  */
30 PtsToBam::
31 PtsToBam() : WithOutputFile(true, false, true)
32 {
33  set_program_brief("convert point cloud data into a .bam file");
34  set_program_description
35  ("This program reads a point clound in a pts file and outputs a bam files, "
36  "suitable for viewing in Panda.");
37 
38  clear_runlines();
39  add_runline("[opts] input.pts output.bam");
40  add_runline("[opts] -o output.bam input.pts");
41 
42  add_option
43  ("o", "filename", 0,
44  "Specify the filename to which the resulting .bam file will be written. "
45  "If this option is omitted, the last parameter name is taken to be the "
46  "name of the output file.",
47  &PtsToBam::dispatch_filename, &_got_output_filename, &_output_filename);
48 
49  add_option
50  ("d", "divisor", 0,
51  "Decimates the point cloud by the indicated divisor. The number of points\n"
52  "added is 1/divisor; numbers larger than 1.0 mean correspondingly fewer\n"
53  "points.",
54  &PtsToBam::dispatch_double, nullptr, &_decimate_divisor);
55 
56  _decimate_divisor = 1.0;
57 }
58 
59 /**
60  *
61  */
62 void PtsToBam::
63 run() {
64  pifstream pts;
65  _pts_filename.set_text();
66  if (!_pts_filename.open_read(pts)) {
67  nout << "Cannot open " << _pts_filename << "\n";
68  exit(1);
69  }
70 
71  _gnode = new GeomNode(_pts_filename.get_basename());
72 
73  _num_points_expected = 0;
74  _num_points_found = 0;
75  _num_points_added = 0;
76  _decimate_factor = 1.0 / std::max(1.0, _decimate_divisor);
77  _line_number = 0;
78  _point_number = 0;
79  _decimated_point_number = 0.0;
80  _num_vdatas = 0;
81  string line;
82  while (std::getline(pts, line)) {
83  process_line(line);
84  }
85  close_vertex_data();
86 
87  nout << "\nFound " << _num_points_found << " points of " << _num_points_expected << " expected.\n";
88  nout << "Generated " << _num_points_added << " points to bam file.\n";
89 
90  // This should be guaranteed because we pass false to the constructor,
91  // above.
92  nassertv(has_output_filename());
93 
94  Filename filename = get_output_filename();
95  filename.make_dir();
96  nout << "Writing " << filename << "\n";
97  BamFile bam_file;
98  if (!bam_file.open_write(filename)) {
99  nout << "Error in writing.\n";
100  exit(1);
101  }
102 
103  if (!bam_file.write_object(_gnode.p())) {
104  nout << "Error in writing.\n";
105  exit(1);
106  }
107 }
108 
109 /**
110  *
111  */
112 bool PtsToBam::
113 handle_args(ProgramBase::Args &args) {
114  if (args.empty()) {
115  nout << "You must specify the pts file to read on the command line.\n";
116  return false;
117  }
118 
119  if (args.size() > 1) {
120  nout << "Specify only one pts on the command line.\n";
121  return false;
122  }
123 
124  _pts_filename = Filename::from_os_specific(args[0]);
125 
126  return true;
127 }
128 
129 /**
130  * Reads a single line from the pts file.
131  */
132 void PtsToBam::
133 process_line(const string &line) {
134  _line_number++;
135 
136  if (_line_number % 1000000 == 0) {
137  std::cerr << "." << std::flush;
138  }
139 
140  if (line.empty() || !isdigit(line[0])) {
141  return;
142  }
143 
144  if (_line_number == 1) {
145  // The first line might be just the number of points.
146  vector_string words;
147  tokenize(trim(line), words, " \t", true);
148  if (words.size() == 1) {
149  string tail;
150  _num_points_expected = string_to_int(words[0], tail);
151  nout << "Expecting " << _num_points_expected << " points, will generate "
152  << (int)(_num_points_expected * _decimate_factor) << "\n";
153  return;
154  }
155  }
156 
157  // Here we might have a point.
158  _num_points_found++;
159  _decimated_point_number += _decimate_factor;
160  int point_number = int(_decimated_point_number);
161  if (point_number > _point_number) {
162  _point_number = point_number;
163 
164  vector_string words;
165  tokenize(trim(line), words, " \t", true);
166  if (words.size() >= 3) {
167  add_point(words);
168  }
169  }
170 }
171 
172 /**
173  * Adds a point from the pts file.
174  */
175 void PtsToBam::
176 add_point(const vector_string &words) {
177  if (_data == nullptr || _data->get_num_rows() >= egg_max_vertices) {
178  open_vertex_data();
179  }
180 
181  string tail;
182  double x, y, z;
183  x = string_to_double(words[0], tail);
184  y = string_to_double(words[1], tail);
185  z = string_to_double(words[2], tail);
186  _vertex.add_data3d(x, y, z);
187  _num_points_added++;
188 }
189 
190 /**
191  * Creates a new GeomVertexData.
192  */
193 void PtsToBam::
194 open_vertex_data() {
195  if (_data != nullptr) {
196  close_vertex_data();
197  }
199  _data = new GeomVertexData("pts", format, GeomEnums::UH_static);
200  _vertex = GeomVertexWriter(_data, "vertex");
201 }
202 
203 /**
204  * Closes a previous GeomVertexData and adds it to the scene graph.
205  */
206 void PtsToBam::
207 close_vertex_data() {
208  if (_data == nullptr) {
209  return;
210  }
211 
212  _num_vdatas++;
213  nout << "\nGenerating " << _num_points_added << " points in " << _num_vdatas << " GeomVertexDatas\n";
214 
215  PT(Geom) geom = new Geom(_data);
216 
217  int num_vertices = _data->get_num_rows();
218  int vertices_so_far = 0;
219  while (num_vertices > 0) {
220  int this_num_vertices = std::min(num_vertices, (int)egg_max_indices);
221  PT(GeomPrimitive) points = new GeomPoints(GeomEnums::UH_static);
222  points->add_consecutive_vertices(vertices_so_far, this_num_vertices);
223  geom->add_primitive(points);
224  vertices_so_far += this_num_vertices;
225  num_vertices -= this_num_vertices;
226  }
227 
228  _gnode->add_geom(geom);
229 
230  _data = nullptr;
231 }
232 
233 int main(int argc, char *argv[]) {
234  PtsToBam prog;
235  prog.parse_command_line(argc, argv);
236  prog.run();
237  return 0;
238 }
The principle public interface to reading and writing Bam disk files.
Definition: bamFile.h:41
int string_to_int(const string &str, string &tail)
A string-interface wrapper around the C library strtol().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool write_object(const TypedWritable *object)
Writes the indicated object to the Bam file.
Definition: bamFile.cxx:226
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
double string_to_double(const string &str, string &tail)
A string-interface wrapper around the C library strtol().
Defines a series of disconnected points.
Definition: geomPoints.h:23
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
void set_text()
Indicates that the filename represents a text file.
Definition: filename.I:424
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Definition: filename.cxx:1863
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename get_output_filename() const
If has_output_filename() returns true, this is the filename that the user specified.
bool has_output_filename() const
Returns true if the user specified an output filename, false otherwise (e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
Definition: geom.h:54
string trim(const string &str)
Returns a new string representing the contents of the given string with both leading and trailing whi...
void add_data3d(double x, double y, double z)
Sets the write row to a particular 3-component value, and advances the write row.
std::string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:367
This is the bare functionality (intended to be inherited from along with ProgramBase or some derivati...
This class defines the physical layout of the vertex data stored within a Geom.
void tokenize(const string &str, vector_string &words, const string &delimiters, bool discard_repeated_delimiters)
Chops the source string up into pieces delimited by any of the characters specified in delimiters.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool make_dir() const
Creates all the directories in the path to the file specified in the filename, except for the basenam...
Definition: filename.cxx:2484
bool open_write(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated file for writing.
Definition: bamFile.cxx:190
static const GeomVertexFormat * get_v3()
Returns a standard vertex format with just a 3-component vertex position.
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328