40 #include <console_bridge/console.h>
102 Sphere::Sphere(
double r) : Shape()
105 throw std::runtime_error(
"Sphere radius must be non-negative.");
110 Cylinder::Cylinder() : Shape()
113 length = radius = 0.0;
116 Cylinder::Cylinder(
double r,
double l) : Shape()
119 throw std::runtime_error(
"Cylinder dimensions must be non-negative.");
125 Cone::Cone() :
Shape()
128 length = radius = 0.0;
134 throw std::runtime_error(
"Cone dimensions must be non-negative.");
143 size[0] = size[1] = size[2] = 0.0;
148 if (
x < 0 ||
y < 0 ||
z < 0)
149 throw std::runtime_error(
"Box dimensions must be non-negative.");
163 triangle_normals =
nullptr;
164 vertex_normals =
nullptr;
170 vertex_count = v_count;
171 vertices =
new double[v_count * 3];
172 triangle_count = t_count;
173 triangles =
new unsigned int[t_count * 3];
174 triangle_normals =
new double[t_count * 3];
175 vertex_normals =
new double[v_count * 3];
196 Plane::Plane(
double pa,
double pb,
double pc,
double pd) : Shape()
239 for (
unsigned int i = 0; i < n; ++i)
242 for (
unsigned int i = 0; i < n; ++i)
249 n = 3 * triangle_count;
250 for (
unsigned int i = 0; i < n; ++i)
252 if (triangle_normals)
253 for (
unsigned int i = 0; i < n; ++i)
263 Plane* Plane::clone()
const
265 return new Plane(a, b, c,
d);
268 OcTree* OcTree::clone()
const
270 return new OcTree(octree);
273 void OcTree::scaleAndPadd(
double ,
double )
275 CONSOLE_BRIDGE_logWarn(
"OcTrees cannot be scaled or padded");
278 void Plane::scaleAndPadd(
double ,
double )
280 CONSOLE_BRIDGE_logWarn(
"Planes cannot be scaled or padded");
283 void Shape::scale(
double scale)
285 scaleAndPadd(scale, 0.0);
288 void Shape::padd(
double padding)
290 scaleAndPadd(1.0, padding);
293 void Sphere::scaleAndPadd(
double scale,
double padding)
295 const auto tmpRadius = radius * scale + padding;
297 throw std::runtime_error(
"Sphere radius must be non-negative.");
301 void Cylinder::scaleAndPadd(
double scaleRadius,
double scaleLength,
double paddRadius,
double paddLength)
303 const auto tmpRadius = radius * scaleRadius + paddRadius;
304 const auto tmpLength = length * scaleLength + 2.0 * paddLength;
305 if (tmpRadius < 0 || tmpLength < 0)
306 throw std::runtime_error(
"Cylinder dimensions must be non-negative.");
311 void Cylinder::scale(
double scaleRadius,
double scaleLength)
313 scaleAndPadd(scaleRadius, scaleLength, 0.0, 0.0);
316 void Cylinder::padd(
double paddRadius,
double paddLength)
318 scaleAndPadd(1.0, 1.0, paddRadius, paddLength);
321 void Cylinder::scaleAndPadd(
double scale,
double padd)
323 scaleAndPadd(scale, scale, padd, padd);
326 void Cone::scaleAndPadd(
double scaleRadius,
double scaleLength,
double paddRadius,
double paddLength)
328 const auto tmpRadius = radius * scaleRadius + paddRadius;
329 const auto tmpLength = length * scaleLength + 2.0 * paddLength;
330 if (tmpRadius < 0 || tmpLength < 0)
331 throw std::runtime_error(
"Cone dimensions must be non-negative.");
336 void Cone::scale(
double scaleRadius,
double scaleLength)
338 scaleAndPadd(scaleRadius, scaleLength, 0.0, 0.0);
341 void Cone::padd(
double paddRadius,
double paddLength)
343 scaleAndPadd(1.0, 1.0, paddRadius, paddLength);
346 void Cone::scaleAndPadd(
double scale,
double padd)
348 scaleAndPadd(scale, scale, padd, padd);
351 void Box::scaleAndPadd(
double scaleX,
double scaleY,
double scaleZ,
double paddX,
double paddY,
double paddZ)
353 const auto tmpSize0 = size[0] * scaleX + paddX * 2.0;
354 const auto tmpSize1 = size[1] * scaleY + paddY * 2.0;
355 const auto tmpSize2 = size[2] * scaleZ + paddZ * 2.0;
356 if (tmpSize0 < 0 || tmpSize1 < 0 || tmpSize2 < 0)
357 throw std::runtime_error(
"Box dimensions must be non-negative.");
363 void Box::scale(
double scaleX,
double scaleY,
double scaleZ)
365 scaleAndPadd(scaleX, scaleY, scaleZ, 0.0, 0.0, 0.0);
368 void Box::padd(
double paddX,
double paddY,
double paddZ)
370 scaleAndPadd(1.0, 1.0, 1.0, paddX, paddY, paddZ);
373 void Box::scaleAndPadd(
double scale,
double padd)
375 scaleAndPadd(scale, scale, scale, padd, padd, padd);
378 void Mesh::scaleAndPadd(
double scaleX,
double scaleY,
double scaleZ,
double paddX,
double paddY,
double paddZ)
381 double sx = 0.0, sy = 0.0, sz = 0.0;
382 for (
unsigned int i = 0; i < vertex_count; ++i)
384 unsigned int i3 = i * 3;
386 sy += vertices[i3 + 1];
387 sz += vertices[i3 + 2];
389 sx /= (double)vertex_count;
390 sy /= (double)vertex_count;
391 sz /= (double)vertex_count;
394 for (
unsigned int i = 0; i < vertex_count; ++i)
396 unsigned int i3 = i * 3;
399 double dx = vertices[i3] - sx;
400 double dy = vertices[i3 + 1] - sy;
401 double dz = vertices[i3 + 2] - sz;
404 double scaledX = sx + dx * scaleX;
405 double scaledY = sy + dy * scaleY;
406 double scaledZ = sz + dz * scaleZ;
408 vertices[i3] = scaledX + vertex_normals[i3] * paddX;
409 vertices[i3 + 1] = scaledY + vertex_normals[i3 + 1] * paddY;
410 vertices[i3 + 2] = scaledZ + vertex_normals[i3 + 2] * paddZ;
414 void Mesh::scale(
double scaleX,
double scaleY,
double scaleZ)
416 scaleAndPadd(scaleX, scaleY, scaleZ, 0.0, 0.0, 0.0);
419 void Mesh::padd(
double paddX,
double paddY,
double paddZ)
421 scaleAndPadd(1.0, 1.0, 1.0, paddX, paddY, paddZ);
424 void Mesh::scaleAndPadd(
double scale,
double padd)
426 scaleAndPadd(scale, scale, scale, padd, padd, padd);
429 void Shape::print(std::ostream& out)
const
431 out <<
this << std::endl;
434 void Sphere::print(std::ostream& out)
const
436 out <<
"Sphere[radius=" << radius <<
"]" << std::endl;
439 void Cylinder::print(std::ostream& out)
const
441 out <<
"Cylinder[radius=" << radius <<
", length=" << length <<
"]" << std::endl;
444 void Cone::print(std::ostream& out)
const
446 out <<
"Cone[radius=" << radius <<
", length=" << length <<
"]" << std::endl;
449 void Box::print(std::ostream& out)
const
451 out <<
"Box[x=length=" << size[0] <<
", y=width=" << size[1] <<
"z=height=" << size[2] <<
"]" << std::endl;
454 void Mesh::print(std::ostream& out)
const
456 out <<
"Mesh[vertices=" << vertex_count <<
", triangles=" << triangle_count <<
"]" << std::endl;
459 void Plane::print(std::ostream& out)
const
461 out <<
"Plane[a=" << a <<
", b=" << b <<
", c=" << c <<
", d=" <<
d <<
"]" << std::endl;
464 void OcTree::print(std::ostream& out)
const
468 double minx, miny, minz, maxx, maxy, maxz;
469 octree->getMetricMin(minx, miny, minz);
470 octree->getMetricMax(maxx, maxy, maxz);
471 out <<
"OcTree[depth = " << octree->getTreeDepth() <<
", resolution = " << octree->getResolution()
472 <<
" inside box (minx=" << minx <<
", miny=" << miny <<
", minz=" << minz <<
", maxx=" << maxx
473 <<
", maxy=" << maxy <<
", maxz=" << maxz <<
")]" << std::endl;
476 out <<
"OcTree[NULL]" << std::endl;
479 bool Shape::isFixed()
const
484 bool OcTree::isFixed()
const
489 bool Plane::isFixed()
const
494 void Mesh::computeTriangleNormals()
496 if (triangle_count && !triangle_normals)
497 triangle_normals =
new double[triangle_count * 3];
500 for (
unsigned int i = 0; i < triangle_count; ++i)
502 unsigned int i3 = i * 3;
503 Eigen::Vector3d s1(vertices[triangles[i3] * 3] - vertices[triangles[i3 + 1] * 3],
504 vertices[triangles[i3] * 3 + 1] - vertices[triangles[i3 + 1] * 3 + 1],
505 vertices[triangles[i3] * 3 + 2] - vertices[triangles[i3 + 1] * 3 + 2]);
506 Eigen::Vector3d s2(vertices[triangles[i3 + 1] * 3] - vertices[triangles[i3 + 2] * 3],
507 vertices[triangles[i3 + 1] * 3 + 1] - vertices[triangles[i3 + 2] * 3 + 1],
508 vertices[triangles[i3 + 1] * 3 + 2] - vertices[triangles[i3 + 2] * 3 + 2]);
509 Eigen::Vector3d normal = s1.cross(s2);
511 triangle_normals[i3] = normal.x();
512 triangle_normals[i3 + 1] = normal.y();
513 triangle_normals[i3 + 2] = normal.z();
517 void Mesh::computeVertexNormals()
519 if (!triangle_normals)
520 computeTriangleNormals();
521 if (vertex_count && !vertex_normals)
522 vertex_normals =
new double[vertex_count * 3];
523 Eigen::Map<Eigen::Matrix<double, 3, Eigen::Dynamic>> mapped_normals(vertex_normals, 3, vertex_count);
524 mapped_normals.setZero();
526 for (
unsigned int tIdx = 0; tIdx < triangle_count; ++tIdx)
528 unsigned int tIdx3 = 3 * tIdx;
529 unsigned int tIdx3_1 = tIdx3 + 1;
530 unsigned int tIdx3_2 = tIdx3 + 2;
532 unsigned int v1 = triangles[tIdx3];
533 unsigned int v2 = triangles[tIdx3_1];
534 unsigned int v3 = triangles[tIdx3_2];
537 Eigen::Map<Eigen::Vector3d> p1{ vertices + 3 * v1, 3 };
538 Eigen::Map<Eigen::Vector3d> p2{ vertices + 3 * v2, 3 };
539 Eigen::Map<Eigen::Vector3d> p3{ vertices + 3 * v3, 3 };
542 auto angleBetweenVectors = [](
const Eigen::Vector3d& vec1,
const Eigen::Vector3d& vec2) ->
double {
543 Eigen::AngleAxisd a(Eigen::Quaterniond::FromTwoVectors(vec1, vec2));
546 auto ang1 = angleBetweenVectors(p2 - p1, p3 - p1);
547 auto ang2 = angleBetweenVectors(p1 - p2, p3 - p2);
548 auto ang3 = angleBetweenVectors(p1 - p3, p2 - p3);
551 Eigen::Map<Eigen::Vector3d> triangle_normal{ triangle_normals + tIdx3, 3 };
552 mapped_normals.col(v1) += triangle_normal * ang1;
553 mapped_normals.col(v2) += triangle_normal * ang2;
554 mapped_normals.col(v3) += triangle_normal * ang3;
558 for (
int i = 0; i < mapped_normals.cols(); ++i)
560 auto mapped_normal = mapped_normals.col(i);
561 if (mapped_normal.squaredNorm() != 0.0)
563 mapped_normal.normalize();
568 void Mesh::mergeVertices(
double threshold)
570 const double thresholdSQR = threshold * threshold;
572 std::vector<unsigned int> vertex_map(vertex_count);
576 for (
unsigned int vIdx = 0; vIdx < vertex_count; ++vIdx)
578 orig_vertices[vIdx][0] = vertices[3 * vIdx];
579 orig_vertices[vIdx][1] = vertices[3 * vIdx + 1];
580 orig_vertices[vIdx][2] = vertices[3 * vIdx + 2];
581 vertex_map[vIdx] = vIdx;
584 for (
unsigned int vIdx1 = 0; vIdx1 < vertex_count; ++vIdx1)
586 if (vertex_map[vIdx1] != vIdx1)
589 vertex_map[vIdx1] = compressed_vertices.size();
590 compressed_vertices.push_back(orig_vertices[vIdx1]);
592 for (
unsigned int vIdx2 = vIdx1 + 1; vIdx2 < vertex_count; ++vIdx2)
594 double distanceSQR = (orig_vertices[vIdx1] - orig_vertices[vIdx2]).squaredNorm();
596 vertex_map[vIdx2] = vertex_map[vIdx1];
600 if (compressed_vertices.size() == orig_vertices.size())
604 for (
unsigned int tIdx = 0; tIdx < triangle_count; ++tIdx)
606 unsigned int i3 = 3 * tIdx;
607 triangles[i3] = vertex_map[triangles[i3]];
608 triangles[i3 + 1] = vertex_map[triangles[i3 + 1]];
609 triangles[i3 + 2] = vertex_map[triangles[i3 + 2]];
612 vertex_count = compressed_vertices.size();
614 vertices =
new double[vertex_count * 3];
616 for (
unsigned int vIdx = 0; vIdx < vertex_count; ++vIdx)
618 unsigned int i3 = 3 * vIdx;
619 vertices[i3] = compressed_vertices[vIdx][0];
620 vertices[i3 + 1] = compressed_vertices[vIdx][1];
621 vertices[i3 + 2] = compressed_vertices[vIdx][2];
624 if (triangle_normals)
625 computeTriangleNormals();
627 computeVertexNormals();