ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
MessageProcessor.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <ecvMesh.h>
11 
12 #include <zmq.hpp>
13 
20 
21 using namespace cloudViewer::io::rpc;
22 using namespace cloudViewer::utility;
23 
24 namespace cloudViewer {
25 namespace visualization {
26 
27 std::shared_ptr<zmq::message_t> MessageProcessor::ProcessMessage(
28  const messages::Request& req,
29  const messages::SetMeshData& msg,
30  const msgpack::object_handle& obj) {
31  std::string errstr(":");
32  if (!msg.data.CheckMessage(errstr)) {
33  auto status_err = messages::Status::ErrorProcessingMessage();
34  status_err.str += errstr;
35  msgpack::sbuffer sbuf;
36  messages::Reply reply{status_err.MsgId()};
37  msgpack::pack(sbuf, reply);
38  msgpack::pack(sbuf, status_err);
39  return std::shared_ptr<zmq::message_t>(
40  new zmq::message_t(sbuf.data(), sbuf.size()));
41  }
42 
43  if (msg.data.faces.CheckNonEmpty()) {
44  // create a TriangleMesh
45  ccPointCloud* baseVertices = new ccPointCloud("vertices");
46  assert(baseVertices);
47  baseVertices->setEnabled(false);
48  // DGM: no need to lock it as it is only used by one mesh!
49  baseVertices->setLocked(false);
50  auto mesh = std::make_shared<ccMesh>(baseVertices);
51  mesh->addChild(baseVertices);
52 
53  errstr = "";
54  if (!msg.data.vertices.CheckType(
55  {messages::TypeStr<float>(), messages::TypeStr<double>()},
56  errstr)) {
57  errstr = "Ignoring vertices. vertices have wrong data type:" +
58  errstr;
59  LogInfo(errstr.c_str());
60  } else {
61  baseVertices->reserveThePointsTable(
62  static_cast<unsigned>(msg.data.vertices.shape[0]));
64  const float* ptr = msg.data.vertices.Ptr<float>();
65  for (int64_t i = 0; i < msg.data.vertices.shape[0]; ++i) {
66  baseVertices->addPoint(CCVector3::fromArray(ptr));
67  ptr += 3;
68  }
69  }
71  const double* ptr = msg.data.vertices.Ptr<double>();
72  for (int64_t i = 0; i < msg.data.vertices.shape[0]; ++i) {
73  baseVertices->addPoint(CCVector3::fromArray(ptr));
74  ptr += 3;
75  }
76  }
77  }
78 
79  errstr = "";
80  if (msg.data.vertex_attributes.count("normals")) {
81  const auto& attr_arr = msg.data.vertex_attributes.at("normals");
82  if (!attr_arr.CheckType({messages::TypeStr<float>(),
84  errstr)) {
85  errstr = "Ignoring normals. normals have wrong data type:" +
86  errstr;
87  LogInfo(errstr.c_str());
88  } else if (!attr_arr.CheckShape({-1, 3}, errstr)) {
89  errstr = "Ignoring normals. normals have wrong shape:" + errstr;
90  LogInfo(errstr.c_str());
91  } else {
92  if (!baseVertices->hasNormals()) {
93  if (!baseVertices->reserveTheNormsTable()) {
94  errstr =
95  "Ignoring normals. not enough memory:" + errstr;
96  LogInfo(errstr.c_str());
97  }
98  }
99 
100  if (attr_arr.type == messages::TypeStr<float>()) {
101  const float* ptr = attr_arr.Ptr<float>();
102  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
103  baseVertices->addNorm(CCVector3::fromArray(ptr));
104  ptr += 3;
105  }
106  }
107  if (attr_arr.type == messages::TypeStr<double>()) {
108  const double* ptr = attr_arr.Ptr<double>();
109  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
110  baseVertices->addNorm(CCVector3::fromArray(ptr));
111  ptr += 3;
112  }
113  }
114  }
115  }
116 
117  errstr = "";
118  if (msg.data.vertex_attributes.count("colors")) {
119  const auto& attr_arr = msg.data.vertex_attributes.at("colors");
120  if (!attr_arr.CheckType({messages::TypeStr<float>(),
122  errstr)) {
123  errstr = "Ignoring colors. colors have wrong data type:" +
124  errstr;
125  LogInfo(errstr.c_str());
126  } else if (!attr_arr.CheckShape({-1, 3}, errstr)) {
127  errstr = "Ignoring colors. colors have wrong shape:" + errstr;
128  LogInfo(errstr.c_str());
129  } else {
130  if (!baseVertices->hasColors()) {
131  if (!baseVertices->reserveTheRGBTable()) {
132  errstr = "Ignoring colors. not enough memory:" + errstr;
133  LogInfo(errstr.c_str());
134  }
135  }
136 
137  if (attr_arr.type == messages::TypeStr<float>()) {
138  const float* ptr = attr_arr.Ptr<float>();
139  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
140  baseVertices->addRGBColor(ecvColor::Rgb(
141  static_cast<ColorCompType>(ptr[0] * 255),
142  static_cast<ColorCompType>(ptr[1] * 255),
143  static_cast<ColorCompType>(ptr[2] * 255)));
144  ptr += 3;
145  }
146  }
147  if (attr_arr.type == messages::TypeStr<double>()) {
148  const double* ptr = attr_arr.Ptr<double>();
149  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
150  baseVertices->addRGBColor(ecvColor::Rgb(
151  static_cast<ColorCompType>(ptr[0] * 255),
152  static_cast<ColorCompType>(ptr[1] * 255),
153  static_cast<ColorCompType>(ptr[2] * 255)));
154  ptr += 3;
155  }
156  }
157  }
158  }
159 
160  errstr = "";
161  if (!msg.data.faces.CheckShape({-1, 3}, errstr)) {
162  errstr = "Ignoring faces. Only triangular faces are supported:" +
163  errstr;
164  LogInfo(errstr.c_str());
165  } else if (!msg.data.faces.CheckType({messages::TypeStr<int32_t>(),
166  messages::TypeStr<int64_t>()},
167  errstr)) {
168  errstr = "Ignoring faces. Triangles have wrong data type:" + errstr;
169  LogInfo(errstr.c_str());
170  } else {
171  mesh->reserve(static_cast<std::size_t>(msg.data.faces.shape[0]));
172  if (msg.data.faces.type == messages::TypeStr<int32_t>()) {
173  const int32_t* ptr = msg.data.faces.Ptr<int32_t>();
174  for (int64_t i = 0; i < msg.data.faces.shape[0]; ++i) {
175  mesh->addTriangle(static_cast<unsigned int>(ptr[0]),
176  static_cast<unsigned int>(ptr[1]),
177  static_cast<unsigned int>(ptr[2]));
178  ptr += 3;
179  }
180  }
181  if (msg.data.faces.type == messages::TypeStr<int64_t>()) {
182  const int64_t* ptr = msg.data.faces.Ptr<int64_t>();
183  for (int64_t i = 0; i < msg.data.faces.shape[0]; ++i) {
184  mesh->addTriangle(static_cast<unsigned int>(ptr[0]),
185  static_cast<unsigned int>(ptr[1]),
186  static_cast<unsigned int>(ptr[2]));
187  ptr += 3;
188  }
189  }
190  }
191 
192  SetGeometry(mesh, msg.path, msg.time, msg.layer);
193  } else {
194  // create a PointCloud
195  auto pcd = std::make_shared<ccPointCloud>();
196  if (!msg.data.vertices.CheckType(
197  {messages::TypeStr<float>(), messages::TypeStr<double>()},
198  errstr)) {
199  errstr = "Ignoring vertices. vertices have wrong data type:" +
200  errstr;
201  LogInfo(errstr.c_str());
202  } else {
203  pcd->reserveThePointsTable(
204  static_cast<unsigned>(msg.data.vertices.shape[0]));
205  if (msg.data.vertices.type == messages::TypeStr<float>()) {
206  const float* ptr = msg.data.vertices.Ptr<float>();
207  for (int64_t i = 0; i < msg.data.vertices.shape[0]; ++i) {
208  pcd->addPoint(CCVector3::fromArray(ptr));
209  ptr += 3;
210  }
211  }
212  if (msg.data.vertices.type == messages::TypeStr<double>()) {
213  const double* ptr = msg.data.vertices.Ptr<double>();
214  for (int64_t i = 0; i < msg.data.vertices.shape[0]; ++i) {
215  pcd->addPoint(CCVector3::fromArray(ptr));
216  ptr += 3;
217  }
218  }
219 
220  errstr = "";
221  if (msg.data.vertex_attributes.count("normals")) {
222  const auto& attr_arr = msg.data.vertex_attributes.at("normals");
223  if (!attr_arr.CheckType({messages::TypeStr<float>(),
225  errstr)) {
226  errstr = "Ignoring normals. normals have wrong data type:" +
227  errstr;
228  LogInfo(errstr.c_str());
229  } else if (!attr_arr.CheckShape({-1, 3}, errstr)) {
230  errstr = "Ignoring normals. normals have wrong shape:" +
231  errstr;
232  LogInfo(errstr.c_str());
233  } else {
234  if (!pcd->hasNormals()) {
235  if (!pcd->reserveTheNormsTable()) {
236  errstr = "Ignoring normals. not enough memory:" +
237  errstr;
238  LogInfo(errstr.c_str());
239  }
240  }
241 
242  if (attr_arr.type == messages::TypeStr<float>()) {
243  const float* ptr = attr_arr.Ptr<float>();
244  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
245  pcd->addNorm(CCVector3::fromArray(ptr));
246  ptr += 3;
247  }
248  }
249  if (attr_arr.type == messages::TypeStr<double>()) {
250  const double* ptr = attr_arr.Ptr<double>();
251  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
252  pcd->addNorm(CCVector3::fromArray(ptr));
253  ptr += 3;
254  }
255  }
256  }
257  }
258 
259  errstr = "";
260  if (msg.data.vertex_attributes.count("colors")) {
261  const auto& attr_arr = msg.data.vertex_attributes.at("colors");
262  if (!attr_arr.CheckType({messages::TypeStr<float>(),
264  errstr)) {
265  errstr = "Ignoring colors. colors have wrong data type:" +
266  errstr;
267  LogInfo(errstr.c_str());
268  } else if (!attr_arr.CheckShape({-1, 3}, errstr)) {
269  errstr = "Ignoring colors. colors have wrong shape:" +
270  errstr;
271  LogInfo(errstr.c_str());
272  } else {
273  if (!pcd->hasColors()) {
274  if (!pcd->reserveTheRGBTable()) {
275  errstr = "Ignoring colors. not enough memory:" +
276  errstr;
277  LogInfo(errstr.c_str());
278  }
279  }
280 
281  if (attr_arr.type == messages::TypeStr<float>()) {
282  const float* ptr = attr_arr.Ptr<float>();
283  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
284  pcd->addRGBColor(ecvColor::Rgb(
285  static_cast<ColorCompType>(ptr[0] * 255),
286  static_cast<ColorCompType>(ptr[1] * 255),
287  static_cast<ColorCompType>(ptr[2] * 255)));
288  ptr += 3;
289  }
290  }
291  if (attr_arr.type == messages::TypeStr<double>()) {
292  const double* ptr = attr_arr.Ptr<double>();
293  for (int64_t i = 0; i < attr_arr.shape[0]; ++i) {
294  pcd->addRGBColor(ecvColor::Rgb(
295  static_cast<ColorCompType>(ptr[0] * 255),
296  static_cast<ColorCompType>(ptr[1] * 255),
297  static_cast<ColorCompType>(ptr[2] * 255)));
298  ptr += 3;
299  }
300  }
301  }
302  }
303  }
304  SetGeometry(pcd, msg.path, msg.time, msg.layer);
305  }
306 
307  return CreateStatusOKMsg();
308 }
309 
310 void MessageProcessor::SetGeometry(std::shared_ptr<ccHObject> geom,
311  const std::string& path,
312  int time,
313  const std::string& layer) {
314  gui::Application::GetInstance().PostToMainThread(
315  window_, [this, geom, path, time, layer]() {
316  on_geometry_(geom, path, time, layer);
317  });
318 }
319 
320 } // namespace visualization
321 } // namespace cloudViewer
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
virtual void setLocked(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:117
virtual void setEnabled(bool state)
Sets the "enabled" property.
Definition: ecvObject.h:102
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
bool hasNormals() const override
Returns whether normals are enabled or not.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
bool reserveThePointsTable(unsigned _numberOfPoints)
Reserves memory to store the points coordinates.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
std::shared_ptr< zmq::message_t > ProcessMessage(const io::rpc::messages::Request &req, const io::rpc::messages::SetMeshData &msg, const msgpack::object_handle &obj) override
RGB color structure.
Definition: ecvColorTypes.h:49
#define LogInfo(...)
Definition: Logging.h:81
unsigned char ColorCompType
Default color components type (R,G and B)
Definition: ecvColorTypes.h:29
ccGuiPythonInstance * GetInstance() noexcept
Definition: Runtime.cpp:72
std::string TypeStr< float >()
Definition: Messages.h:44
std::string TypeStr< double >()
Definition: Messages.h:48
std::string TypeStr< int32_t >()
Definition: Messages.h:60
std::string TypeStr< int64_t >()
Definition: Messages.h:64
std::shared_ptr< zmq::message_t > CreateStatusOKMsg()
static const std::string path
Definition: PointCloud.cpp:59
Generic file read and write utility for python interface.
bool CheckNonEmpty(std::string &errstr) const
Definition: Messages.h:212
std::vector< int64_t > shape
Definition: Messages.h:142
bool CheckType(const std::vector< std::string > &expected_types, std::string &errstr) const
Definition: Messages.h:233
std::map< std::string, Array > vertex_attributes
Definition: Messages.h:268
bool CheckMessage(std::string &errstr) const
Definition: Messages.h:368
Array vertices
shape must be [num_verts,3]
Definition: Messages.h:265
MeshData data
The data to be set.
Definition: Messages.h:404