Skip to content

Commit

Permalink
check & warn for inf/nan values in input
Browse files Browse the repository at this point in the history
  • Loading branch information
nmwsharp committed Dec 30, 2024
1 parent 7161de6 commit 6d7d811
Show file tree
Hide file tree
Showing 18 changed files with 168 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/polyscope/camera_parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class CameraParameters {
// create/test 'invalid' params
static CameraParameters createInvalid();
bool isValid() const;
bool isfinite() const;

// The intrinsic & extrinsics parameters that define the camera
CameraIntrinsics intrinsics;
Expand Down
28 changes: 28 additions & 0 deletions include/polyscope/check_invalid_values.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run

#pragma once

#include <polyscope/numeric_helpers.h>
#include <polyscope/options.h>

#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtx/compatibility.hpp>
#include <type_traits>

namespace polyscope {

template <typename T>
void checkInvalidValues(std::string name, const std::vector<T>& data) {
if (options::warnForInvalidValues) {
for (const T& val : data) {
if (!allComponentsFinite(val)) {
warning("Invalid +-inf or NaN values detected.\n(set warnForInvalidValues=false to disable this warning)",
"In buffer: " + name);
break;
}
}
}
}

} // namespace polyscope
4 changes: 3 additions & 1 deletion include/polyscope/color_quantity.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ namespace polyscope {

template <typename QuantityT>
ColorQuantity<QuantityT>::ColorQuantity(QuantityT& quantity_, const std::vector<glm::vec3>& colors_)
: quantity(quantity_), colors(&quantity, quantity.uniquePrefix() + "colors", colorsData), colorsData(colors_) {}
: quantity(quantity_), colors(&quantity, quantity.uniquePrefix() + "colors", colorsData), colorsData(colors_) {
colors.checkInvalidValues();
}

template <typename QuantityT>
void ColorQuantity<QuantityT>::buildColorUI() {}
Expand Down
84 changes: 84 additions & 0 deletions include/polyscope/numeric_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run

#pragma once

#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtx/compatibility.hpp>
#include <type_traits>

namespace polyscope {


// Base case: call the scalar version
template <typename T>
bool allComponentsFinite(const T& x) {
return std::isfinite(x);
}

template <>
inline bool allComponentsFinite<glm::vec2>(const glm::vec2& x) {
return glm::all(glm::isfinite(x));
}
template <>
inline bool allComponentsFinite<glm::vec3>(const glm::vec3& x) {
return glm::all(glm::isfinite(x));
}
template <>
inline bool allComponentsFinite<glm::vec4>(const glm::vec4& x) {
return glm::all(glm::isfinite(x));
}

template <>
inline bool allComponentsFinite<glm::uvec2>(const glm::uvec2& x) {
return true;
}
template <>
inline bool allComponentsFinite<glm::uvec3>(const glm::uvec3& x) {
return true;
}
template <>
inline bool allComponentsFinite<glm::uvec4>(const glm::uvec4& x) {
return true;
}

template <>
inline bool allComponentsFinite<glm::mat2x2>(const glm::mat2x2& x) {
for (size_t i = 0; i < 2; i++)
if (!allComponentsFinite(glm::row(x, i))) return false;
return true;
}
template <>
inline bool allComponentsFinite<glm::mat3x3>(const glm::mat3x3& x) {
for (size_t i = 0; i < 3; i++)
if (!allComponentsFinite(glm::row(x, i))) return false;
return true;
}
template <>
inline bool allComponentsFinite<glm::mat4x4>(const glm::mat4x4& x) {
for (size_t i = 0; i < 4; i++)
if (!allComponentsFinite(glm::row(x, i))) return false;
return true;
}

template <>
inline bool allComponentsFinite<std::array<glm::vec3, 2>>(const std::array<glm::vec3, 2>& x) {
for (size_t i = 0; i < x.size(); i++)
if (!glm::all(glm::isfinite(x[i]))) return false;
return true;
}
template <>
inline bool allComponentsFinite<std::array<glm::vec3, 3>>(const std::array<glm::vec3, 3>& x) {
for (size_t i = 0; i < x.size(); i++)
if (!glm::all(glm::isfinite(x[i]))) return false;
return true;
}
template <>
inline bool allComponentsFinite<std::array<glm::vec3, 4>>(const std::array<glm::vec3, 4>& x) {
for (size_t i = 0; i < x.size(); i++)
if (!glm::all(glm::isfinite(x[i]))) return false;
return true;
}


} // namespace polyscope
3 changes: 3 additions & 0 deletions include/polyscope/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ extern bool giveFocusOnShow;
// If true, hide the polyscope window when a show() command finishes (default: true)
extern bool hideWindowAfterShow;

// Give warnings for inf/nan values
extern bool warnForInvalidValues;

// === Scene options

// Behavior of the ground plane
Expand Down
5 changes: 3 additions & 2 deletions include/polyscope/parameterization_quantity.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ ParameterizationQuantity<QuantityT>::ParameterizationQuantity(QuantityT& quantit
gridBackgroundColor(quantity.uniquePrefix() + "#gridBackgroundColor", render::RGB_PINK),
altDarkness(quantity.uniquePrefix() + "#altDarkness", 0.5), cMap(quantity.uniquePrefix() + "#cMap", "phase")
{}
{
coords.checkInvalidValues();
}
template <typename QuantityT>
Expand Down
2 changes: 2 additions & 0 deletions include/polyscope/render/managed_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class ManagedBuffer : public virtual WeakReferrable {
bool dataGetsComputed; // if true, the value gets computed on-demand by calling computeFunc()
std::function<void()> computeFunc; // (optional) callback which populates the `data` buffer

// sanity check helper
void checkInvalidValues();

// mark as texture, set size
void setTextureSize(uint32_t sizeX);
Expand Down
3 changes: 3 additions & 0 deletions include/polyscope/scalar_quantity.ipp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run

#include "imgui.h"
#include "polyscope/check_invalid_values.h"
#include "polyscope/utilities.h"

namespace polyscope {

template <typename QuantityT>
Expand All @@ -17,6 +19,7 @@ ScalarQuantity<QuantityT>::ScalarQuantity(QuantityT& quantity_, const std::vecto
isolineDarkness(quantity.uniquePrefix() + "isolineDarkness", 0.7)

{
values.checkInvalidValues();
hist.updateColormap(cMap.get());
hist.buildHistogram(values.data);

Expand Down
5 changes: 4 additions & 1 deletion include/polyscope/vector_quantity.ipp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run


#include "polyscope/standardize_data_array.h"

namespace polyscope {
Expand Down Expand Up @@ -125,6 +124,7 @@ VectorQuantity<QuantityT>::VectorQuantity(QuantityT& quantity_, const std::vecto
: VectorQuantityBase<QuantityT>(quantity_, vectorType_),
vectors(&quantity_, quantity_.uniquePrefix() + "#values", vectorsData), vectorRoots(vectorRoots_),
vectorsData(vectors_) {
vectors.checkInvalidValues();
this->updateMaxLength();
}
Expand Down Expand Up @@ -236,6 +236,9 @@ TangentVectorQuantity<QuantityT>::TangentVectorQuantity(QuantityT& quantity_,
tangentBasisY(&quantity_, quantity_.uniquePrefix() + "#basisY", tangentBasisYData), vectorRoots(vectorRoots_),
tangentVectorsData(tangentVectors_), tangentBasisXData(tangentBasisX_), tangentBasisYData(tangentBasisY_),
nSym(nSym_) {
tangentVectors.checkInvalidValues();
tangentBasisX.checkInvalidValues();
tangentBasisY.checkInvalidValues();
this->updateMaxLength();
}
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ SET(HEADERS
${INCLUDE_ROOT}/camera_parameters.ipp
${INCLUDE_ROOT}/camera_view.h
${INCLUDE_ROOT}/camera_view.ipp
${INCLUDE_ROOT}/check_invalid_values.h
${INCLUDE_ROOT}/color_management.h
${INCLUDE_ROOT}/color_image_quantity.h
${INCLUDE_ROOT}/color_render_image_quantity.h
Expand Down Expand Up @@ -293,6 +294,7 @@ SET(HEADERS
${INCLUDE_ROOT}/implicit_helpers.h
${INCLUDE_ROOT}/implicit_helpers.ipp
${INCLUDE_ROOT}/messages.h
${INCLUDE_ROOT}/numeric_helpers.h
${INCLUDE_ROOT}/options.h
${INCLUDE_ROOT}/parameterization_quantity.h
${INCLUDE_ROOT}/parameterization_quantity.ipp
Expand Down
16 changes: 16 additions & 0 deletions src/camera_parameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include "polyscope/camera_parameters.h"

#include "polyscope/numeric_helpers.h"
#include "polyscope/options.h"

#include <cmath>
#include <iostream>

Expand Down Expand Up @@ -171,6 +174,19 @@ CameraParameters CameraParameters::createInvalid() {
}
bool CameraParameters::isValid() const { return intrinsics.isValid() && extrinsics.isValid(); }

bool CameraParameters::isfinite() const {
// confusing: two different notions of "valid". Here we mean "finite". There's another notion above which uses a flag
// to mark not-set-yet params.

bool isValid = true;

isValid = isValid && allComponentsFinite(intrinsics.getAspectRatioWidthOverHeight());
isValid = isValid && allComponentsFinite(intrinsics.getFoVVerticalDegrees());
isValid = isValid && allComponentsFinite(extrinsics.getE());

return isValid;
}

// == Forwarding getters for the camera class

glm::vec3 CameraParameters::getT() const { return extrinsics.getT(); }
Expand Down
7 changes: 7 additions & 0 deletions src/camera_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ CameraView::CameraView(std::string name, const CameraParameters& params_)
widgetThickness(uniquePrefix() + "#widgetThickness", 0.02),
widgetColor(uniquePrefix() + "#widgetColor", glm::vec3{0., 0., 0.}) {

if (options::warnForInvalidValues) {
if (!params.isfinite()) {
warning("Invalid +-inf or NaN values detected.\n(set warnForInvalidValues=false to disable this warning)",
"In camera view: " + name);
}
}

updateObjectSpaceBounds();
}

Expand Down
1 change: 1 addition & 0 deletions src/curve_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ CurveNetwork::CurveNetwork(std::string name, std::vector<glm::vec3> nodes_, std:
material(uniquePrefix() + "#material", "clay")
// clang-format on
{
nodePositions.checkInvalidValues();
// Copy interleaved data in to tip and tails buffers below
edgeTailIndsData.resize(edges_.size());
Expand Down
1 change: 1 addition & 0 deletions src/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ bool automaticallyComputeSceneExtents = true;
bool invokeUserCallbackForNestedShow = false;
bool giveFocusOnShow = false;
bool hideWindowAfterShow = true;
bool warnForInvalidValues = true;

bool screenshotTransparency = true;
std::string screenshotExtension = ".png";
Expand Down
1 change: 1 addition & 0 deletions src/point_cloud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ PointCloud::PointCloud(std::string name, std::vector<glm::vec3> points_)
material(uniquePrefix() + "material", "clay")
// clang-format on
{
points.checkInvalidValues();
cullWholeElements.setPassive(true);
updateObjectSpaceBounds();
}
Expand Down
6 changes: 6 additions & 0 deletions src/render/managed_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "polyscope/render/managed_buffer.h"

#include "polyscope/check_invalid_values.h"
#include "polyscope/internal.h"
#include "polyscope/messages.h"
#include "polyscope/polyscope.h"
Expand Down Expand Up @@ -39,6 +40,11 @@ ManagedBuffer<T>::ManagedBuffer(ManagedBufferRegistry* registry_, const std::str
template <typename T>
ManagedBuffer<T>::~ManagedBuffer() {}

template <typename T>
void ManagedBuffer<T>::checkInvalidValues() {
polyscope::checkInvalidValues(name, data);
}

template <typename T>
void ManagedBuffer<T>::setTextureSize(uint32_t sizeX_) {
if (deviceBufferType != DeviceBufferType::Attribute) exception("managed buffer can only be set as texture once");
Expand Down
2 changes: 2 additions & 0 deletions src/surface_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ SurfaceMesh::SurfaceMesh(std::string name_, const std::vector<glm::vec3>& vertex
faceIndsEntries = faceIndsEntries_;
faceIndsStart = faceIndsStart_;

vertexPositions.checkInvalidValues();
computeConnectivityData();
updateObjectSpaceBounds();
}
Expand All @@ -84,6 +85,7 @@ SurfaceMesh::SurfaceMesh(std::string name_, const std::vector<glm::vec3>& vertex
vertexPositionsData = vertexPositions_;
nestedFacesToFlat(facesIn);

vertexPositions.checkInvalidValues();
computeConnectivityData();
updateObjectSpaceBounds();
}
Expand Down
1 change: 1 addition & 0 deletions src/volume_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ edgeWidth(uniquePrefix() + "edgeWidth", 0.),
activeLevelSetQuantity(nullptr)
{
// clang-format on
vertexPositions.checkInvalidValues();

cullWholeElements.setPassive(true);

Expand Down

0 comments on commit 6d7d811

Please sign in to comment.