ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvExtru.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 
8 #include "ecvExtru.h"
9 
10 // CV_DB_LIB
11 #include "ecvNormalVectors.h"
12 #include "ecvPointCloud.h"
13 
14 // cloudViewer
15 #include <Delaunay2dMesh.h>
16 
17 // system
18 #include <string.h>
19 
20 ccExtru::ccExtru(const std::vector<CCVector2>& profile,
22  const ccGLMatrix* transMat /*= 0*/,
23  QString name /*="Extrusion"*/)
24  : ccGenericPrimitive(name, transMat), m_height(height), m_profile(profile) {
25  assert(m_profile.size() > 2);
26 
28 }
29 
30 ccExtru::ccExtru(QString name /*="Plane"*/)
31  : ccGenericPrimitive(name), m_height(0) {}
32 
34  return finishCloneJob(
36 }
37 
39  unsigned count = static_cast<unsigned>(m_profile.size());
40  if (count < 3) return false;
41 
43 
44  // DGM: we check that last vertex is different from the first one!
45  //(yes it happens ;)
46  if (m_profile.back().x == m_profile.front().x &&
47  m_profile.back().y == m_profile.front().y)
48  --count;
49 
50  std::string errorStr;
51  if (!mesh.buildMesh(m_profile, count, errorStr)) {
52  CVLog::Warning(QString("[ccPlane::buildUp] Profile triangulation "
53  "failed (cloudViewer said: '%1'")
54  .arg(QString::fromStdString(errorStr)));
55  return false;
56  }
57 
58  unsigned numberOfTriangles = mesh.size();
59  int* triIndexes = mesh.getTriangleVertIndexesArray();
60 
61  if (numberOfTriangles == 0) return false;
62 
63  // vertices
64  unsigned vertCount = 2 * count;
65  // faces
66  unsigned faceCount = 2 * numberOfTriangles + 2 * count;
67  // faces normals
68  unsigned faceNormCount = 2 + count;
69 
70  if (!init(vertCount, false, faceCount, faceNormCount)) {
71  CVLog::Error("[ccPlane::buildUp] Not enough memory");
72  return false;
73  }
74 
75  ccPointCloud* verts = vertices();
76  assert(verts);
77  assert(m_triNormals);
78 
79  // bottom & top faces normals
81  ccNormalVectors::GetNormIndex(CCVector3(0.0, 0.0, -1.0).u));
83  ccNormalVectors::GetNormIndex(CCVector3(0.0, 0.0, 1.0).u));
84 
85  // add profile vertices & normals
86  for (unsigned i = 0; i < count; ++i) {
87  const CCVector2& P = m_profile[i];
88  verts->addPoint(CCVector3(P.x, P.y, 0));
89  verts->addPoint(CCVector3(P.x, P.y, m_height));
90 
91  const CCVector2& PNext = m_profile[(i + 1) % count];
92  CCVector2 N(-(PNext.y - P.y), PNext.x - P.x);
93  N.normalize();
95  ccNormalVectors::GetNormIndex(CCVector3(N.x, N.y, 0.0).u));
96  }
97 
98  // add faces
99  {
100  // side faces
101  {
102  const int* _triIndexes = triIndexes;
103  for (unsigned i = 0; i < numberOfTriangles; ++i, _triIndexes += 3) {
104  addTriangle(_triIndexes[0] * 2, _triIndexes[2] * 2,
105  _triIndexes[1] * 2);
106  addTriangleNormalIndexes(0, 0, 0);
107  addTriangle(_triIndexes[0] * 2 + 1, _triIndexes[1] * 2 + 1,
108  _triIndexes[2] * 2 + 1);
109  addTriangleNormalIndexes(1, 1, 1);
110  }
111  }
112 
113  // thickness
114  {
115  for (unsigned i = 0; i < count; ++i) {
116  unsigned iNext = ((i + 1) % count);
117  addTriangle(i * 2, i * 2 + 1, iNext * 2);
118  addTriangleNormalIndexes(2 + i, 2 + i, 2 + i);
119  addTriangle(iNext * 2, i * 2 + 1, iNext * 2 + 1);
120  addTriangleNormalIndexes(2 + i, 2 + i, 2 + i);
121  }
122  }
123  }
124 
125  return true;
126 }
127 
128 bool ccExtru::toFile_MeOnly(QFile& out, short dataVersion) const {
129  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
130  if (dataVersion < 21) {
131  assert(false);
132  return false;
133  }
134 
135  if (!ccGenericPrimitive::toFile_MeOnly(out, dataVersion)) return false;
136 
137  // parameters (dataVersion>=21)
138  QDataStream outStream(&out);
139  outStream << m_height;
140  // profile size
141  outStream << (qint32)m_profile.size();
142  // profile points (2D)
143  for (unsigned i = 0; i < m_profile.size(); ++i) {
144  outStream << m_profile[i].x;
145  outStream << m_profile[i].y;
146  }
147 
148  return true;
149 }
150 
152  return std::max(static_cast<short>(21),
154 }
155 
157  short dataVersion,
158  int flags,
159  LoadedIDMap& oldToNewIDMap) {
160  if (!ccGenericPrimitive::fromFile_MeOnly(in, dataVersion, flags,
161  oldToNewIDMap))
162  return false;
163 
164  // parameters (dataVersion>=21)
165  QDataStream inStream(&in);
167  // profile size
168  qint32 vertCount;
169  inStream >> vertCount;
170  if (vertCount) {
171  m_profile.resize(vertCount);
172  // profile points (2D)
173  for (unsigned i = 0; i < m_profile.size(); ++i) {
175  m_profile[i].u, 2);
176  }
177  } else {
178  return false;
179  }
180 
181  return true;
182 }
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
Definition: CVGeom.h:798
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
std::string name
int height
int count
CloudViewerScene::LightingProfile profile
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
Type u[3]
Definition: CVGeom.h:139
Type x
Definition: CVGeom.h:36
Type y
Definition: CVGeom.h:36
void addElement(const Type &value)
Definition: ecvArray.h:105
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
Definition: ecvExtru.cpp:156
short minimumFileVersion_MeOnly() const override
Definition: ecvExtru.cpp:151
PointCoordinateType m_height
Extrusion thickness.
Definition: ecvExtru.h:63
std::vector< CCVector2 > m_profile
Profile.
Definition: ecvExtru.h:66
ccExtru(const std::vector< CCVector2 > &profile, PointCoordinateType height, const ccGLMatrix *transMat=0, QString name=QString("Extrusion"))
Default constructor.
Definition: ecvExtru.cpp:20
virtual bool buildUp() override
Builds primitive.
Definition: ecvExtru.cpp:38
virtual ccGenericPrimitive * clone() const override
Clones primitive.
Definition: ecvExtru.cpp:33
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
Definition: ecvExtru.cpp:128
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
Generic primitive interface.
bool init(unsigned vertCount, bool vertNormals, unsigned faceCount, unsigned faceNormCount)
Inits internal structures.
virtual bool updateRepresentation()
Updates internal representation (as a mesh)
ccGenericPrimitive * finishCloneJob(ccGenericPrimitive *primitive) const
Finished 'clone' job (vertices color, etc.)
ccPointCloud * vertices()
Returns vertices.
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
ccGLMatrix m_transformation
Associated transformation (applied to vertices)
short minimumFileVersion_MeOnly() const override
NormsIndexesTableType * m_triNormals
Per-triangle normals.
Definition: ecvMesh.h:1493
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
Definition: ecvMesh.cpp:2428
void addTriangleNormalIndexes(int i1, int i2, int i3)
Adds a triplet of normal indexes for next triangle.
Definition: ecvMesh.cpp:3340
static CompressedNormType GetNormIndex(const PointCoordinateType N[])
Returns the compressed index corresponding to a normal vector.
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
QMultiMap< unsigned, unsigned > LoadedIDMap
Map of loaded unique IDs (old ID --> new ID)
static void CoordsFromDataStream(QDataStream &stream, int flags, PointCoordinateType *out, unsigned count=1)
A class to compute and handle a Delaunay 2D mesh on a subset of points.
virtual unsigned size() const override
Returns the number of triangles.
virtual bool buildMesh(const std::vector< CCVector2 > &points2D, std::size_t pointCountToUse, std::string &outputErrorStr)
Build the Delaunay mesh on top a set of 2D points.
int * getTriangleVertIndexesArray()
Returns triangles indexes array (pointer to)
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.