Commit ee064ec9 authored by David Flynn's avatar David Flynn
Browse files

maths: be explicit in the computation type of Vec3::getNorm2 + friends

The result and computation types of Vec3<T>::getNorm2 were assumed to
be T.  This works fine for floating point types, but leads to overflow
when the underlying vector is Vec3<int32_t>.  This commit requires the
caller to supply the result of the computation type as a template
parameter to getNorm2.
parent 52848dbf
...@@ -79,12 +79,17 @@ public: ...@@ -79,12 +79,17 @@ public:
const T& y() const { return data[1]; } const T& y() const { return data[1]; }
const T& z() const { return data[2]; } const T& z() const { return data[2]; }
T getNorm() const { return static_cast<T>(sqrt(getNorm2())); } template<typename ResultT>
T getNorm2() const { return (*this) * (*this); } ResultT getNorm2() const
{
return Vec3<ResultT>(*this) * Vec3<ResultT>(*this);
}
T getNormInf() const T getNormInf() const
{ {
return std::max(data[2], std::max(abs(data[0]), abs(data[1]))); return std::max(data[2], std::max(abs(data[0]), abs(data[1])));
} }
Vec3& operator=(const Vec3& rhs) Vec3& operator=(const Vec3& rhs)
{ {
memcpy(data, rhs.data, sizeof(data)); memcpy(data, rhs.data, sizeof(data));
...@@ -394,11 +399,13 @@ struct Box3 { ...@@ -394,11 +399,13 @@ struct Box3 {
&& max.z() >= box.min.z() && min.z() <= box.max.z(); && max.z() >= box.min.z() && min.z() <= box.max.z();
} }
T getDist2(const Vec3<T>& point) const template<typename SquaredT>
SquaredT getDist2(const Vec3<T>& point) const
{ {
const T dx = std::max(std::max(min[0] - point[0], T()), point[0] - max[0]); using U = SquaredT;
const T dy = std::max(std::max(min[1] - point[1], T()), point[1] - max[1]); U dx = U(std::max(std::max(min[0] - point[0], T()), point[0] - max[0]));
const T dz = std::max(std::max(min[2] - point[2], T()), point[2] - max[2]); U dy = U(std::max(std::max(min[1] - point[1], T()), point[1] - max[1]));
U dz = U(std::max(std::max(min[2] - point[2], T()), point[2] - max[2]));
return dx * dx + dy * dy + dz * dz; return dx * dx + dy * dy + dz * dz;
} }
......
...@@ -490,7 +490,7 @@ FindNeighborWithinDistance( ...@@ -490,7 +490,7 @@ FindNeighborWithinDistance(
const int32_t index1 = retained[j]; const int32_t index1 = retained[j];
const int32_t pointIndex1 = packedVoxel[index1].index; const int32_t pointIndex1 = packedVoxel[index1].index;
const auto& point1 = pointCloud[pointIndex1]; const auto& point1 = pointCloud[pointIndex1];
const auto d2 = (point1 - point).getNorm2(); const auto d2 = (point1 - point).getNorm2<double>();
if (d2 <= radius2) { if (d2 <= radius2) {
return index1; return index1;
} }
...@@ -666,7 +666,9 @@ computeNearestNeighbors( ...@@ -666,7 +666,9 @@ computeNearestNeighbors(
aps.scalable_lifting_enabled_flag, nodeSizeLog2, aps.scalable_lifting_enabled_flag, nodeSizeLog2,
pointCloud[pointIndex1]); pointCloud[pointIndex1]);
double norm2 = times(point - point1, aps.lod_neigh_bias).getNorm2(); double norm2 =
times(point - point1, aps.lod_neigh_bias).getNorm2<double>();
if (nodeSizeLog2 > 0 && point == point1) { if (nodeSizeLog2 > 0 && point == point1) {
norm2 = double(1 << (nodeSizeLog2 - 1)); norm2 = double(1 << (nodeSizeLog2 - 1));
norm2 = norm2 * norm2; norm2 = norm2 * norm2;
...@@ -686,7 +688,7 @@ computeNearestNeighbors( ...@@ -686,7 +688,7 @@ computeNearestNeighbors(
} }
if ( if (
predictor.neighborCount < aps.num_pred_nearest_neighbours predictor.neighborCount < aps.num_pred_nearest_neighbours
|| bBoxes[bucketIndex1].getDist2(point) || bBoxes[bucketIndex1].getDist2<int64_t>(point)
<= predictor.neighbors[index0].weight) { <= predictor.neighbors[index0].weight) {
const int32_t k0 = std::max(bucketIndex1 * bucketSize, j0); const int32_t k0 = std::max(bucketIndex1 * bucketSize, j0);
const int32_t k1 = std::min((bucketIndex1 + 1) * bucketSize, j1); const int32_t k1 = std::min((bucketIndex1 + 1) * bucketSize, j1);
...@@ -697,7 +699,8 @@ computeNearestNeighbors( ...@@ -697,7 +699,8 @@ computeNearestNeighbors(
pointCloud[pointIndex1]); pointCloud[pointIndex1]);
double norm2 = double norm2 =
times(point - point1, aps.lod_neigh_bias).getNorm2(); times(point - point1, aps.lod_neigh_bias).getNorm2<double>();
if (nodeSizeLog2 > 0 && point == point1) { if (nodeSizeLog2 > 0 && point == point1) {
norm2 = (double)(1 << (nodeSizeLog2 - 1)); norm2 = (double)(1 << (nodeSizeLog2 - 1));
norm2 = norm2 * norm2; norm2 = norm2 * norm2;
...@@ -720,9 +723,9 @@ computeNearestNeighbors( ...@@ -720,9 +723,9 @@ computeNearestNeighbors(
for (int32_t k = k0; k < k1; ++k) { for (int32_t k = k0; k < k1; ++k) {
const int32_t pointIndex1 = packedVoxel[indexes[startIndex + k]].index; const int32_t pointIndex1 = packedVoxel[indexes[startIndex + k]].index;
const auto& point1 = pointCloud[pointIndex1]; const auto& point1 = pointCloud[pointIndex1];
auto d2 = times(point - point1, aps.lod_neigh_bias).getNorm2<double>();
predictor.insertNeighbor( predictor.insertNeighbor(
pointIndex1, times(point - point1, aps.lod_neigh_bias).getNorm2(), pointIndex1, d2, aps.num_pred_nearest_neighbours,
aps.num_pred_nearest_neighbours,
startIndex + k - i + 2 * aps.search_range); startIndex + k - i + 2 * aps.search_range);
} }
...@@ -734,7 +737,7 @@ computeNearestNeighbors( ...@@ -734,7 +737,7 @@ computeNearestNeighbors(
if ( if (
predictor.neighborCount < aps.num_pred_nearest_neighbours predictor.neighborCount < aps.num_pred_nearest_neighbours
|| bBoxesI[bucketIndex1].getDist2(point) || bBoxesI[bucketIndex1].getDist2<int64_t>(point)
<= predictor.neighbors[index0].weight) { <= predictor.neighbors[index0].weight) {
const int32_t k0 = bucketIndex1 * bucketSize; const int32_t k0 = bucketIndex1 * bucketSize;
const int32_t k1 = std::min((bucketIndex1 + 1) * bucketSize, j1); const int32_t k1 = std::min((bucketIndex1 + 1) * bucketSize, j1);
...@@ -742,10 +745,11 @@ computeNearestNeighbors( ...@@ -742,10 +745,11 @@ computeNearestNeighbors(
const int32_t pointIndex1 = const int32_t pointIndex1 =
packedVoxel[indexes[startIndex + k]].index; packedVoxel[indexes[startIndex + k]].index;
const auto& point1 = pointCloud[pointIndex1]; const auto& point1 = pointCloud[pointIndex1];
auto d2 =
times(point - point1, aps.lod_neigh_bias).getNorm2<double>();
predictor.insertNeighbor( predictor.insertNeighbor(
pointIndex1, pointIndex1, d2, aps.num_pred_nearest_neighbours,
times(point - point1, aps.lod_neigh_bias).getNorm2(),
aps.num_pred_nearest_neighbours,
startIndex + k - i + 2 * aps.search_range); startIndex + k - i + 2 * aps.search_range);
} }
} }
...@@ -776,9 +780,11 @@ subsampleByDistance( ...@@ -776,9 +780,11 @@ subsampleByDistance(
continue; continue;
} }
const auto& point = pointCloud[packedVoxel[index].index]; const auto& point = pointCloud[packedVoxel[index].index];
const auto& lastRetained =
pointCloud[packedVoxel[retained.back()].index];
auto distanceToLastRetained = (lastRetained - point).getNorm2<double>();
if ( if (
(pointCloud[packedVoxel[retained.back()].index] - point).getNorm2() distanceToLastRetained <= radius2
<= radius2
|| FindNeighborWithinDistance( || FindNeighborWithinDistance(
pointCloud, packedVoxel, index, radius2, searchRange, retained) pointCloud, packedVoxel, index, radius2, searchRange, retained)
!= PCC_UNDEFINED_INDEX) { != PCC_UNDEFINED_INDEX) {
......
...@@ -294,7 +294,7 @@ recolourColour( ...@@ -294,7 +294,7 @@ recolourColour(
double maxAttributeDist2 = std::numeric_limits<double>::min(); double maxAttributeDist2 = std::numeric_limits<double>::min();
for (int i = 0; i < nNN; ++i) { for (int i = 0; i < nNN; ++i) {
for (int j = 0; j < nNN; ++j) { for (int j = 0; j < nNN; ++j) {
const double dist2 = (colors[i] - colors[j]).getNorm2(); const double dist2 = (colors[i] - colors[j]).getNorm2<double>();
if (dist2 > maxAttributeDist2) { if (dist2 > maxAttributeDist2) {
maxAttributeDist2 = dist2; maxAttributeDist2 = dist2;
} }
...@@ -416,7 +416,7 @@ recolourColour( ...@@ -416,7 +416,7 @@ recolourColour(
double maxAttributeDist2 = std::numeric_limits<double>::min(); double maxAttributeDist2 = std::numeric_limits<double>::min();
for (int i = 0; i < nNN; ++i) { for (int i = 0; i < nNN; ++i) {
for (int j = 0; j < nNN; ++j) { for (int j = 0; j < nNN; ++j) {
const double dist2 = (colors[i] - colors[j]).getNorm2(); const double dist2 = (colors[i] - colors[j]).getNorm2<double>();
if (dist2 > maxAttributeDist2) { if (dist2 > maxAttributeDist2) {
maxAttributeDist2 = dist2; maxAttributeDist2 = dist2;
} }
...@@ -462,7 +462,7 @@ recolourColour( ...@@ -462,7 +462,7 @@ recolourColour(
} }
} }
const double r = double(pointCountTarget) / double(pointCountSource); const double r = double(pointCountTarget) / double(pointCountSource);
const double delta2 = (centroid2 - centroid1).getNorm2(); const double delta2 = (centroid2 - centroid1).getNorm2<double>();
const double eps = 0.000001; const double eps = 0.000001;
const bool fixWeight = 1; // m42538 const bool fixWeight = 1; // m42538
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment