ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvDish.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 "ecvDish.h"
9 
10 // Local
11 #include "ecvNormalVectors.h"
12 #include "ecvPointCloud.h"
13 
16  PointCoordinateType radius2 /*=0*/,
17  const ccGLMatrix* transMat /*=0*/,
18  QString name /*="Dish"*/,
19  unsigned precision /*=DEFAULT_DRAWING_PRECISION*/)
20  : ccGenericPrimitive(name, transMat),
21  m_baseRadius(radius),
22  m_secondRadius(radius2),
23  m_height(height) {
24  if (radius2 == 0)
25  m_height = std::min(
26  height,
27  radius); // in spherical mode, the height can't be superior to
28  // the radius! (dishes are at most hemispheres)
29  setDrawingPrecision(std::max<unsigned>(
30  precision,
31  MIN_DRAWING_PRECISION)); // automatically calls buildUp +
32  // applyTransformationToVertices
33 }
34 
35 ccDish::ccDish(QString name /*="Sphere"*/)
37  m_baseRadius(0),
38  m_secondRadius(0),
39  m_height(0) {}
40 
45 }
46 
48  if (m_drawPrecision < MIN_DRAWING_PRECISION) return false;
49 
50  if (m_height <= 0 || m_baseRadius <= 0 ||
51  m_secondRadius < 0) // invalid parameters
52  return false;
53 
54  // section angular span
55  double startAngle_rad = 0.0;
56  const double endAngle_rad = M_PI / 2.0;
57 
58  PointCoordinateType realRadius = m_baseRadius;
59  if (m_secondRadius == 0 &&
60  m_height < m_baseRadius) // partial spherical mode
61  {
62  realRadius = (m_height * m_height + m_baseRadius * m_baseRadius) /
63  (2 * m_height);
64  startAngle_rad = acos(m_baseRadius / realRadius);
65  assert(startAngle_rad < endAngle_rad);
66  }
67 
68  const unsigned steps = m_drawPrecision;
69  double angleStep_rad = 2.0 * M_PI / steps;
70  unsigned sectionSteps = static_cast<unsigned>(ceil(
71  (endAngle_rad - startAngle_rad) * m_drawPrecision / (2.0 * M_PI)));
72  double sectionAngleStep_rad =
73  (endAngle_rad - startAngle_rad) / sectionSteps;
74 
75  // vertices
76  unsigned vertCount = steps * sectionSteps + 1; //+1 for north pole
77  // faces
78  unsigned faceCount = steps * ((sectionSteps - 1) * 2 + 1);
79 
80  if (!init(vertCount, true, faceCount, 0)) {
81  CVLog::Error("[ccDish::buildUp] Not enough memory");
82  return false;
83  }
84 
85  // vertices
86  ccPointCloud* verts = vertices();
87  assert(verts);
88 
89  // first point: north pole
90  verts->addPoint(CCVector3(0, 0, m_height));
91  verts->addNorm(CCVector3(0, 0, 1));
92 
93  // then, angular sweep
94  {
95  for (unsigned j = 1; j <= sectionSteps; ++j) {
96  PointCoordinateType theta = static_cast<PointCoordinateType>(
97  endAngle_rad -
98  j * sectionAngleStep_rad); // we start from north pole!
99  PointCoordinateType cos_theta = cos(theta);
100  PointCoordinateType sin_theta = sin(theta);
101 
102  CCVector3 N0(cos_theta, 0, sin_theta);
103 
104  for (unsigned i = 0; i < steps;
105  ++i) // then we make a full revolution
106  {
107  PointCoordinateType phi =
108  static_cast<PointCoordinateType>(i * angleStep_rad);
109  PointCoordinateType cos_phi = cos(phi);
110  PointCoordinateType sin_phi = sin(phi);
111 
112  CCVector3 N(N0.x * cos_phi, N0.x * sin_phi, N0.z);
113  N.normalize();
114 
115  CCVector3 P = N * realRadius;
116 
117  if (m_secondRadius > 0) // half-ellipsoid mode
118  {
119  P.y *= (m_secondRadius / m_baseRadius);
120  P.z *= (m_height / m_baseRadius);
121  } else // spherical section mode
122  {
123  P.z += m_height - realRadius;
124  }
125 
126  verts->addPoint(P);
127  verts->addNorm(N);
128  }
129  }
130  }
131 
132  // faces
133  {
134  // north pole
135  {
136  for (unsigned i = 0; i < steps; ++i) {
137  unsigned A = 1 + i;
138  unsigned B = (i + 1 < steps ? A + 1 : 1);
139  addTriangle(A, B, 0);
140  }
141  }
142 
143  // slices
144  for (unsigned j = 1; j < sectionSteps; ++j) {
145  unsigned shift = 1 + (j - 1) * steps;
146  for (unsigned i = 0; i < steps; ++i) {
147  unsigned A = shift + i;
148  unsigned B = (i + 1 < steps ? A + 1 : shift);
149  assert(B < vertCount);
150  addTriangle(A, A + steps, B);
151  addTriangle(B + steps, B, A + steps);
152  }
153  }
154  }
155 
157  showNormals(true);
158 
159  return true;
160 }
161 
162 bool ccDish::toFile_MeOnly(QFile& out, short dataVersion) const {
163  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
164  if (dataVersion < 21) {
165  assert(false);
166  return false;
167  }
168 
169  if (!ccGenericPrimitive::toFile_MeOnly(out, dataVersion)) return false;
170 
171  // parameters (dataVersion>=21)
172  QDataStream outStream(&out);
173  outStream << m_baseRadius;
174  outStream << m_secondRadius;
175  outStream << m_height;
176 
177  return true;
178 }
179 
181  return std::max(static_cast<short>(21),
183 }
184 
185 bool ccDish::fromFile_MeOnly(QFile& in,
186  short dataVersion,
187  int flags,
188  LoadedIDMap& oldToNewIDMap) {
189  if (!ccGenericPrimitive::fromFile_MeOnly(in, dataVersion, flags,
190  oldToNewIDMap))
191  return false;
192 
193  // parameters (dataVersion>=21)
194  QDataStream inStream(&in);
197  &m_secondRadius);
199 
200  return true;
201 }
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 x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
void normalize()
Sets vector norm to unity.
Definition: CVGeom.h:428
virtual ccGenericPrimitive * clone() const override
Clones primitive.
Definition: ecvDish.cpp:41
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
Definition: ecvDish.cpp:162
PointCoordinateType m_baseRadius
Base radius.
Definition: ecvDish.h:72
virtual bool buildUp() override
Builds primitive.
Definition: ecvDish.cpp:47
ccDish(PointCoordinateType radius, PointCoordinateType height, PointCoordinateType radius2=0, const ccGLMatrix *transMat=0, QString name=QString("Dish"), unsigned precision=DEFAULT_DRAWING_PRECISION)
Default constructor.
Definition: ecvDish.cpp:14
PointCoordinateType m_secondRadius
Second radius.
Definition: ecvDish.h:74
short minimumFileVersion_MeOnly() const override
Definition: ecvDish.cpp:180
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
Definition: ecvDish.cpp:185
PointCoordinateType m_height
Height.
Definition: ecvDish.h:76
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
void showNormals(bool state) override
Sets normals visibility.
Generic primitive interface.
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.
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
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
Definition: ecvMesh.cpp:2428
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
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.
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89