ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvCone.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 "ecvCone.h"
9 
10 // Local
11 #include "ecvNormalVectors.h"
12 #include "ecvPointCloud.h"
13 
15  PointCoordinateType topRadius,
17  PointCoordinateType xOff /*=0*/,
18  PointCoordinateType yOff /*=0*/,
19  const ccGLMatrix* transMat /*=0*/,
20  QString name /*="Cylinder"*/,
21  unsigned precision /*=DEFAULT_DRAWING_PRECISION*/)
22  : ccGenericPrimitive(name, transMat),
23  m_bottomRadius(fabs(bottomRadius)),
24  m_topRadius(fabs(topRadius)),
25  m_xOff(xOff),
26  m_yOff(yOff),
27  m_height(fabs(height)) {
28  setDrawingPrecision(std::max<unsigned>(
29  precision,
30  MIN_DRAWING_PRECISION)); // automatically calls buildUp &
31  // applyTransformationToVertices
32 }
33 
34 ccCone::ccCone(QString name /*="Cylinder"*/)
36  m_bottomRadius(0),
37  m_topRadius(0),
38  m_xOff(0),
39  m_yOff(0),
40  m_height(0) {}
41 
46 }
47 
49  if (m_drawPrecision < MIN_DRAWING_PRECISION) return false;
50 
51  // invalid dimensions?
54  return false;
55  }
56 
57  // topology
58  bool singlePointBottom = cloudViewer::LessThanEpsilon(m_bottomRadius);
59  bool singlePointTop = cloudViewer::LessThanEpsilon(m_topRadius);
60  assert(!singlePointBottom || !singlePointTop);
61 
62  unsigned steps = m_drawPrecision;
63 
64  // vertices
65  unsigned vertCount = 2;
66  if (!singlePointBottom) vertCount += steps;
67  if (!singlePointTop) vertCount += steps;
68  // normals
69  unsigned faceNormCounts = steps + 2;
70  // vertices
71  unsigned facesCount = steps;
72  if (!singlePointBottom) facesCount += steps;
73  if (!singlePointTop) facesCount += steps;
74  if (!singlePointBottom && !singlePointTop) facesCount += steps;
75 
76  // allocate (& clear) structures
77  if (!init(vertCount, false, facesCount, faceNormCounts)) {
78  CVLog::Error("[ccCone::buildUp] Not enough memory");
79  return false;
80  }
81 
82  ccPointCloud* verts = vertices();
83  assert(verts);
84  assert(m_triNormals);
85 
86  // 2 first points: centers of the top & bottom surfaces
87  CCVector3 bottomCenter = CCVector3(m_xOff, m_yOff, -m_height) / 2;
88  CCVector3 topCenter = CCVector3(-m_xOff, -m_yOff, m_height) / 2;
89  {
90  // bottom center
91  verts->addPoint(bottomCenter);
92  CompressedNormType nIndex =
94  m_triNormals->addElement(nIndex);
95  // top center
96  verts->addPoint(topCenter);
97  nIndex = ccNormalVectors::GetNormIndex(CCVector3(0, 0, 1).u);
98  m_triNormals->addElement(nIndex);
99  }
100 
101  // then, angular sweep for top and/or bottom surfaces
102  {
103  PointCoordinateType angle_rad_step =
104  static_cast<PointCoordinateType>(2.0 * M_PI) /
105  static_cast<PointCoordinateType>(steps);
106  // bottom surface
107  if (!singlePointBottom) {
108  for (unsigned i = 0; i < steps; ++i) {
109  CCVector3 P(bottomCenter.x +
110  cos(angle_rad_step * i) * m_bottomRadius,
111  bottomCenter.y +
112  sin(angle_rad_step * i) * m_bottomRadius,
113  bottomCenter.z);
114  verts->addPoint(P);
115  }
116  }
117  // top surface
118  if (!singlePointTop) {
119  for (unsigned i = 0; i < steps; ++i) {
120  CCVector3 P(topCenter.x + cos(angle_rad_step * i) * m_topRadius,
121  topCenter.y + sin(angle_rad_step * i) * m_topRadius,
122  topCenter.z);
123  verts->addPoint(P);
124  }
125  }
126  // side normals
127  {
128  for (unsigned i = 0; i < steps; ++i) {
129  // slope
130  CCVector3 u(-sin(angle_rad_step * i), cos(angle_rad_step * i),
131  0);
132  CCVector3 v(bottomCenter.x - topCenter.x +
133  u.y * (m_bottomRadius - m_topRadius),
134  bottomCenter.y - topCenter.y -
135  u.x * (m_bottomRadius - m_topRadius),
136  bottomCenter.z - topCenter.z);
137  CCVector3 N = v.cross(u);
138  N.normalize();
139 
141  m_triNormals->addElement(nIndex);
142  }
143  }
144  }
145 
146  // mesh faces
147  {
148  assert(m_triVertIndexes);
149 
150  unsigned bottomIndex = 2;
151  unsigned topIndex = 2 + (singlePointBottom ? 0 : steps);
152 
153  // bottom surface
154  if (!singlePointBottom) {
155  for (unsigned i = 0; i < steps; ++i) {
156  addTriangle(0, bottomIndex + (i + 1) % steps, bottomIndex + i);
157  addTriangleNormalIndexes(0, 0, 0);
158  }
159  }
160  // top surface
161  if (!singlePointTop) {
162  for (unsigned i = 0; i < steps; ++i) {
163  addTriangle(1, topIndex + i, topIndex + (i + 1) % steps);
164  addTriangleNormalIndexes(1, 1, 1);
165  }
166  }
167 
168  if (!singlePointBottom && !singlePointTop) {
169  for (unsigned i = 0; i < steps; ++i) {
170  unsigned iNext = (i + 1) % steps;
171  addTriangle(bottomIndex + i, bottomIndex + iNext, topIndex + i);
172  addTriangleNormalIndexes(2 + i, 2 + iNext, 2 + i);
173  addTriangle(topIndex + i, bottomIndex + iNext,
174  topIndex + iNext);
175  addTriangleNormalIndexes(2 + i, 2 + iNext, 2 + iNext);
176  }
177  } else if (!singlePointTop) {
178  for (unsigned i = 0; i < steps; ++i) {
179  unsigned iNext = (i + 1) % steps;
180  addTriangle(topIndex + i, 0, topIndex + iNext);
181  addTriangleNormalIndexes(2 + i, 2 + iNext,
182  2 + iNext); // TODO: middle normal
183  // should be halfbetween?!
184  }
185  } else // if (!singlePointBottom)
186  {
187  for (unsigned i = 0; i < steps; ++i) {
188  unsigned iNext = (i + 1) % steps;
189  addTriangle(bottomIndex + i, bottomIndex + iNext, 1);
191  2 + i, 2 + iNext,
192  2 + i); // TODO: last normal should be halfbetween?!
193  }
194  }
195  }
196 
198  showTriNorms(true);
199 
200  return true;
201 }
202 
204  if (m_height == height) return;
205 
206  assert(height > 0);
207  m_height = height;
208 
209  buildUp();
211 }
212 
214  if (m_bottomRadius == radius) return;
215 
216  assert(radius > 0);
217  m_bottomRadius = radius;
218 
219  buildUp();
221 }
222 
224  if (m_topRadius == radius) return;
225 
226  assert(radius > 0);
227  m_topRadius = radius;
228 
229  buildUp();
231 }
232 
234  CCVector3 bottomCenter = CCVector3(m_xOff, m_yOff, -m_height) / 2;
236  trans.apply(bottomCenter);
237  return bottomCenter;
238 }
240  CCVector3 topCenter = CCVector3(-m_xOff, -m_yOff, m_height) / 2;
242  trans.apply(topCenter);
243  return topCenter;
244 }
245 
247  if (m_topRadius <= m_bottomRadius) {
248  return getTopCenter();
249  }
250  return getBottomCenter();
251 }
252 
254  if (m_topRadius >= m_bottomRadius) {
255  return getTopCenter();
256  }
257  return getBottomCenter();
258 }
259 
261  if (m_topRadius <= m_bottomRadius) {
262  return m_topRadius;
263  }
264  return m_bottomRadius;
265 }
266 
268  if (m_topRadius >= m_bottomRadius) {
269  return m_topRadius;
270  }
271  return m_bottomRadius;
272 }
273 
274 bool ccCone::toFile_MeOnly(QFile& out, short dataVersion) const {
275  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
276  if (dataVersion < 21) {
277  assert(false);
278  return false;
279  }
280 
281  if (!ccGenericPrimitive::toFile_MeOnly(out, dataVersion)) return false;
282 
283  // parameters (dataVersion>=21)
284  QDataStream outStream(&out);
285  outStream << m_bottomRadius;
286  outStream << m_topRadius;
287  outStream << m_xOff;
288  outStream << m_yOff;
289  outStream << m_height;
290 
291  return true;
292 }
293 
295  return std::max(static_cast<short>(21),
297 }
298 
299 bool ccCone::fromFile_MeOnly(QFile& in,
300  short dataVersion,
301  int flags,
302  LoadedIDMap& oldToNewIDMap) {
303  if (!ccGenericPrimitive::fromFile_MeOnly(in, dataVersion, flags,
304  oldToNewIDMap))
305  return false;
306 
307  // parameters (dataVersion>=21)
308  QDataStream inStream(&in);
310  &m_bottomRadius);
315 
316  return true;
317 }
constexpr double M_PI
Pi.
Definition: CVConst.h:19
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
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
Type y
Definition: CVGeom.h:137
Type u[3]
Definition: CVGeom.h:139
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
void normalize()
Sets vector norm to unity.
Definition: CVGeom.h:428
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
Definition: CVGeom.h:412
void addElement(const Type &value)
Definition: ecvArray.h:105
virtual PointCoordinateType getLargeRadius() const
Returns whichever cone radii is larger.
Definition: ecvCone.cpp:267
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
Definition: ecvCone.cpp:299
virtual void setBottomRadius(PointCoordinateType radius)
Sets bottom radius.
Definition: ecvCone.cpp:213
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
Definition: ecvCone.cpp:274
PointCoordinateType m_xOff
Displacement of axes along X-axis (Snout mode)
Definition: ecvCone.h:118
short minimumFileVersion_MeOnly() const override
Definition: ecvCone.cpp:294
PointCoordinateType m_height
Height.
Definition: ecvCone.h:124
virtual ccGenericPrimitive * clone() const override
Clones primitive.
Definition: ecvCone.cpp:42
virtual CCVector3 getTopCenter() const
Returns cone axis top end point after applying transformation.
Definition: ecvCone.cpp:239
virtual CCVector3 getBottomCenter() const
Returns cone axis bottom end point after applying transformation.
Definition: ecvCone.cpp:233
virtual bool buildUp() override
Builds primitive.
Definition: ecvCone.cpp:48
virtual CCVector3 getLargeCenter() const
Returns cone axis end point associated with whichever radii is larger.
Definition: ecvCone.cpp:253
PointCoordinateType m_topRadius
Top radius.
Definition: ecvCone.h:115
PointCoordinateType m_bottomRadius
Bottom radius.
Definition: ecvCone.h:112
void setHeight(PointCoordinateType height)
Sets height.
Definition: ecvCone.cpp:203
virtual CCVector3 getSmallCenter() const
Returns cone axis end point associated with whichever radii is smaller.
Definition: ecvCone.cpp:246
virtual PointCoordinateType getSmallRadius() const
Returns whichever cone radii is smaller.
Definition: ecvCone.cpp:260
PointCoordinateType m_yOff
Displacement of axes along Y-axis (Snout mode)
Definition: ecvCone.h:121
virtual void setTopRadius(PointCoordinateType radius)
Sets top radius.
Definition: ecvCone.cpp:223
ccCone(PointCoordinateType bottomRadius, PointCoordinateType topRadius, PointCoordinateType height, PointCoordinateType xOff=0, PointCoordinateType yOff=0, const ccGLMatrix *transMat=0, QString name=QString("Cone"), unsigned precision=DEFAULT_DRAWING_PRECISION)
Default constructor.
Definition: ecvCone.cpp:14
void apply(float vec[3]) const
Applies transformation to a 3D vector (in place) - float version.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
virtual void showTriNorms(bool state)
Sets whether to show or not per-triangle normals.
Generic primitive interface.
void applyTransformationToVertices()
Applies associated transformation to vertices.
bool init(unsigned vertCount, bool vertNormals, unsigned faceCount, unsigned faceNormCount)
Inits internal structures.
virtual bool setDrawingPrecision(unsigned steps)
Sets drawing precision.
ccGenericPrimitive * finishCloneJob(ccGenericPrimitive *primitive) const
Finished 'clone' job (vertices color, etc.)
ccPointCloud * vertices()
Returns vertices.
const ccGLMatrix & getGLTransformationHistory() const override
inherited methods (ccHObject)
unsigned m_drawPrecision
Drawing precision (for primitives that support this feature)
static const int MIN_DRAWING_PRECISION
Minimum drawing precision.
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
virtual void notifyGeometryUpdate()
Definition: ecvHObject.cpp:104
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
triangleIndexesContainer * m_triVertIndexes
Triangles' vertices indexes (3 per triangle)
Definition: ecvMesh.h:1502
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)
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned int CompressedNormType
Compressed normals type.
Definition: ecvBasicTypes.h:16
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
Definition: CVMath.h:23