Skip to content

Commit

Permalink
Rebase from 'release/noetic/geometric_shapes'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhaschke committed May 7, 2024
1 parent 140d463 commit 1955494
Show file tree
Hide file tree
Showing 14 changed files with 62 additions and 158 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Changelog for package geometric_shapes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.7.6 (2024-05-07)
------------------
* Improve padding of meshes using weighted vertex normals (`#238 <https://github.com/ros-planning/geometric_shapes/issues/238>`_)
* Drop obsolete C++ standard definition (`#235 <https://github.com/ros-planning/geometric_shapes/issues/235>`_)
* Contributors: Kenji Brameld (TRACLabs), Michael Görner

0.7.5 (2023-04-12)
------------------
* Limit indefinite growth of OBBs during merging (`#232 <https://github.com/ros-planning/geometric_shapes/issues/232>`_)
Expand Down
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
cmake_minimum_required(VERSION 3.0.2)
project(geometric_shapes)

add_compile_options(-std=c++11)

# Set compile options
set(PROJECT_COMPILE_OPTIONS
-Wall
Expand Down
7 changes: 0 additions & 7 deletions debian/changelog.em

This file was deleted.

1 change: 0 additions & 1 deletion debian/compat.em

This file was deleted.

14 changes: 0 additions & 14 deletions debian/control.em

This file was deleted.

11 changes: 0 additions & 11 deletions debian/copyright.em

This file was deleted.

3 changes: 0 additions & 3 deletions debian/gbp.conf.em

This file was deleted.

67 changes: 0 additions & 67 deletions debian/rules.em

This file was deleted.

1 change: 0 additions & 1 deletion debian/source/format.em

This file was deleted.

6 changes: 0 additions & 6 deletions debian/source/options.em

This file was deleted.

3 changes: 2 additions & 1 deletion include/geometric_shapes/shapes.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ class Mesh : public Shape
/** \brief Compute the normals of each triangle from its vertices via cross product. */
void computeTriangleNormals();

/** \brief Compute vertex normals by averaging from adjacent triangle normals.
/** \brief Compute vertex normals by averaging from adjacent triangle normals, weighted using magnitude of
* angles formed by adjacent triangles at the vertex.
Calls computeTriangleNormals() if needed. */
void computeVertexNormals();
Expand Down
2 changes: 1 addition & 1 deletion package.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<package format="3">
<name>geometric_shapes</name>
<version>0.7.5</version>
<version>0.7.6</version>
<description>Generic definitions of geometric shapes and bodies.</description>

<author email="[email protected]">Ioan Sucan</author>
Expand Down
82 changes: 46 additions & 36 deletions src/shapes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,23 +400,15 @@ void Mesh::scaleAndPadd(double scaleX, double scaleY, double scaleZ, double padd
double dy = vertices[i3 + 1] - sy;
double dz = vertices[i3 + 2] - sz;

// length of vector
double norm = sqrt(dx * dx + dy * dy + dz * dz);
if (norm > 1e-6)
{
vertices[i3] = sx + dx * (scaleX + paddX / norm);
vertices[i3 + 1] = sy + dy * (scaleY + paddY / norm);
vertices[i3 + 2] = sz + dz * (scaleZ + paddZ / norm);
}
else
{
double ndx = ((dx > 0) ? dx + paddX : dx - paddX);
double ndy = ((dy > 0) ? dy + paddY : dy - paddY);
double ndz = ((dz > 0) ? dz + paddZ : dz - paddZ);
vertices[i3] = sx + ndx;
vertices[i3 + 1] = sy + ndy;
vertices[i3 + 2] = sz + ndz;
}
// Scaled coordinate
double scaledX = sx + dx * scaleX;
double scaledY = sy + dy * scaleY;
double scaledZ = sz + dz * scaleZ;

// Padding in each direction
vertices[i3] = scaledX + vertex_normals[i3] * paddX;
vertices[i3 + 1] = scaledY + vertex_normals[i3 + 1] * paddY;
vertices[i3 + 2] = scaledZ + vertex_normals[i3 + 2] * paddZ;
}
}

Expand Down Expand Up @@ -529,7 +521,8 @@ void Mesh::computeVertexNormals()
computeTriangleNormals();
if (vertex_count && !vertex_normals)
vertex_normals = new double[vertex_count * 3];
EigenSTL::vector_Vector3d avg_normals(vertex_count, Eigen::Vector3d(0, 0, 0));
Eigen::Map<Eigen::Matrix<double, 3, Eigen::Dynamic>> mapped_normals(vertex_normals, 3, vertex_count);
mapped_normals.setZero();

for (unsigned int tIdx = 0; tIdx < triangle_count; ++tIdx)
{
Expand All @@ -541,26 +534,43 @@ void Mesh::computeVertexNormals()
unsigned int v2 = triangles[tIdx3_1];
unsigned int v3 = triangles[tIdx3_2];

avg_normals[v1][0] += triangle_normals[tIdx3];
avg_normals[v1][1] += triangle_normals[tIdx3_1];
avg_normals[v1][2] += triangle_normals[tIdx3_2];

avg_normals[v2][0] += triangle_normals[tIdx3];
avg_normals[v2][1] += triangle_normals[tIdx3_1];
avg_normals[v2][2] += triangle_normals[tIdx3_2];

avg_normals[v3][0] += triangle_normals[tIdx3];
avg_normals[v3][1] += triangle_normals[tIdx3_1];
avg_normals[v3][2] += triangle_normals[tIdx3_2];
// Get angles for each vertex at this triangle
Eigen::Map<Eigen::Vector3d> p1{ vertices + 3 * v1, 3 };
Eigen::Map<Eigen::Vector3d> p2{ vertices + 3 * v2, 3 };
Eigen::Map<Eigen::Vector3d> p3{ vertices + 3 * v3, 3 };

// Use re-arranged dot product equation to calculate angle between two vectors
auto angleBetweenVectors = [](const Eigen::Vector3d& vec1, const Eigen::Vector3d& vec2) -> double {
double vec1_norm = vec1.norm();
double vec2_norm = vec2.norm();

// Handle the case where either vector has zero length, to prevent division-by-zero
if (vec1_norm == 0.0 || vec2_norm == 0.0)
return 0.0;

return std::acos(vec1.dot(vec2) / (vec1_norm * vec2_norm));
};

// Use law of cosines to compute angles
auto ang1 = angleBetweenVectors(p2 - p1, p3 - p1);
auto ang2 = angleBetweenVectors(p1 - p2, p3 - p2);
auto ang3 = angleBetweenVectors(p1 - p3, p2 - p3);

// Weight normal with angle
Eigen::Map<Eigen::Vector3d> triangle_normal{ triangle_normals + tIdx3, 3 };
mapped_normals.col(v1) += triangle_normal * ang1;
mapped_normals.col(v2) += triangle_normal * ang2;
mapped_normals.col(v3) += triangle_normal * ang3;
}
for (std::size_t i = 0; i < avg_normals.size(); ++i)

// Normalize each column of the matrix
for (int i = 0; i < mapped_normals.cols(); ++i)
{
if (avg_normals[i].squaredNorm() > 0.0)
avg_normals[i].normalize();
unsigned int i3 = i * 3;
vertex_normals[i3] = avg_normals[i][0];
vertex_normals[i3 + 1] = avg_normals[i][1];
vertex_normals[i3 + 2] = avg_normals[i][2];
auto mapped_normal = mapped_normals.col(i);
if (mapped_normal.squaredNorm() != 0.0)
{
mapped_normal.normalize();
}
}
}

Expand Down
15 changes: 7 additions & 8 deletions test/test_shapes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,10 @@ TEST(Mesh, ScaleAndPadd)
EXPECT_DOUBLE_EQ(mesh2->vertices[22], -2.0);
EXPECT_DOUBLE_EQ(mesh2->vertices[23], 2.0);

// padding actually means extending each vertices' direction vector by the padding value,
// not extending it along each axis by the same amount
// for a right-angled corner, the vertex normal vector points away equally from the three sides, and hence
// padding is applied equally in x, y and z, such that the total distance the vertex moves is equal to 1.0.
mesh2->padd(1.0);
const double pos = 2.0 * (1 + 1.0 / sqrt(12));
const double pos = 2.0 + 1.0 / sqrt(3);

EXPECT_DOUBLE_EQ(mesh2->vertices[0], pos);
EXPECT_DOUBLE_EQ(mesh2->vertices[1], pos);
Expand Down Expand Up @@ -314,7 +314,7 @@ TEST(Mesh, ScaleAndPadd)
EXPECT_DOUBLE_EQ(mesh2->vertices[23], pos);

mesh2->scaleAndPadd(2.0, 1.0);
const double pos2 = pos * (2.0 + 1.0 / sqrt(3 * pos * pos));
const double pos2 = pos * 2.0 + 1.0 / sqrt(3);

EXPECT_DOUBLE_EQ(mesh2->vertices[0], pos2);
EXPECT_DOUBLE_EQ(mesh2->vertices[1], pos2);
Expand Down Expand Up @@ -423,10 +423,9 @@ TEST(Mesh, ScaleAndPadd)
EXPECT_DOUBLE_EQ(mesh2->vertices[23], pos4z);

mesh2->padd(1.0, 2.0, 3.0);
const double norm5 = sqrt(pos4x * pos4x + pos4y * pos4y + pos4z * pos4z);
const double pos5x = pos4x * (1.0 + 1.0 / norm5);
const double pos5y = pos4y * (1.0 + 2.0 / norm5);
const double pos5z = pos4z * (1.0 + 3.0 / norm5);
const double pos5x = pos4x + (1.0 / sqrt(3));
const double pos5y = pos4y + (2.0 / sqrt(3));
const double pos5z = pos4z + (3.0 / sqrt(3));

EXPECT_DOUBLE_EQ(mesh2->vertices[0], pos5x);
EXPECT_DOUBLE_EQ(mesh2->vertices[1], pos5y);
Expand Down

0 comments on commit 1955494

Please sign in to comment.