Skip to content

Commit

Permalink
permute template args
Browse files Browse the repository at this point in the history
  • Loading branch information
nmwsharp committed Jul 17, 2019
1 parent 6373e4c commit b1d2e9f
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 37 deletions.
2 changes: 1 addition & 1 deletion include/polyscope/point_cloud.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class PointCloud : public QuantityStructure<PointCloud> {
// Implementation of templated constructor
template <class T>
PointCloud::PointCloud(std::string name, const T& points_)
: QuantityStructure<PointCloud>(name), points(standardizeVectorArray<glm::vec3, T, 3>(points_)) {
: QuantityStructure<PointCloud>(name), points(standardizeVectorArray<glm::vec3, 3>(points_)) {

initialBaseColor = getNextUniqueColor();
pointColor = initialBaseColor;
Expand Down
4 changes: 2 additions & 2 deletions include/polyscope/point_cloud.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace polyscope {
template <class T>
PointCloudColorQuantity* PointCloud::addColorQuantity(std::string name, const T& colors) {
validateSize(colors, nPoints(), "point cloud color quantity " + name);
return addColorQuantityImpl(name, standardizeVectorArray<glm::vec3, T, 3>(colors));
return addColorQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(colors));
}


Expand All @@ -18,7 +18,7 @@ PointCloudScalarQuantity* PointCloud::addScalarQuantity(std::string name, const
template <class T>
PointCloudVectorQuantity* PointCloud::addVectorQuantity(std::string name, const T& vectors, VectorType vectorType) {
validateSize(vectors, nPoints(), "point cloud vector quantity " + name);
return addVectorQuantityImpl(name, standardizeVectorArray<glm::vec3, T, 3>(vectors), vectorType);
return addVectorQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(vectors), vectorType);
}


Expand Down
47 changes: 25 additions & 22 deletions include/polyscope/standardize_data_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@

// == "How the heck do these work", abridged version:
//
// Nicholas Sharp ([email protected])
//
// (This is Nick's best attempt to explain these functions, during a glorious
// few days in July 2019 when he sorta understood how they work. An actual
// C++ expert could certainly give a better explanation. Pardon misued
// terminology.)
// few days after writing them in July 2019 when he sorta understood how they
// work. An actual C++ expert could certainly give a better explanation. Pardon
// misused terminology.)
//
// These templates abuse C++ to consider many version of a function, and pick
// the one which will compile.
// the one which will compile. We use technique to heuristically convert
// unknown user types to a standard format.
//
// This isn't really something it seems like the language supports, but
// technically you can do it, thanks to a "feature" called SFINAE
Expand All @@ -47,7 +50,7 @@
// ambiguous function calls.
//
// We utilize SFINAE by ensuring that versions of a function which are not
// applicable get discarded during step (2). There are a few ways to do this
// applicable get discarded during step (2). There are a few ways to do this,
// but we'll do it by adding extra template types with default values that
// fail to resolve.
//
Expand Down Expand Up @@ -93,7 +96,7 @@
// (recall, if ::type doesn't exist, it'll halt substitution as
// we discussed in (2) above).
//
// Putting these two together we can require that a function doStuff()
// Putting these two together we can require that a function x.doStuff()
// return an int with a recipe like
//
// template<typename T,
Expand All @@ -109,12 +112,12 @@
// function overloads. We need to make sure that when multiple functions
// are valid, one is always preferred over all others.
//
// Our mechanism to do so will be encluded an extra empty parameter
// PreferenceT<N> in every functions argument list, with a distinct
// value of N. Our Preference<N> // is implicitly convertible to
// PreferenceT<N-1>. So if our initial function call uses
// Our mechanism to do so will be including an extra dummpy parameter
// PreferenceT<N> in every function's argument list, with a distinct
// value of N. Our Preference<N> is implicitly convertible to
// PreferenceT<N-1> (and so on). So if our initial function call uses
// PreferenceT<N_MAX>{}, it will match any of the overloads with lower-
// numbered PreferenceT<> templates. However, since these lower-numbered
// numbered PreferenceT<> parameters. However, since these lower-numbered
// functions involve implicit conversions, they will always have a lower
// priority and not be ambiguous!

Expand Down Expand Up @@ -162,7 +165,7 @@ struct InnerType {

// Note: this dummy function is defined so the non-dependent user function name will always resolve to something;
// some compilers will throw an error if the name doesn't resolve.
void adaptorF_custom_size(void* dont_use) {
inline void adaptorF_custom_size(void* dont_use) {
// dummy function
}

Expand Down Expand Up @@ -225,7 +228,7 @@ size_t adaptorF_size(const T& inputData) {
// and S.
//
// Note: it might be tempting to instead abstract via a function which which accesses the i'th element of the array,
// but that would require that array types be random-accessable. By going to a std::vector, we open the door to
// but that would require that array types be random-accessible. By going to a std::vector, we open the door to
// non-random-accessible input types like iterables.
//
// The following hierarchy of strategies will be attempted, with decreasing precedence:
Expand All @@ -237,13 +240,13 @@ size_t adaptorF_size(const T& inputData) {

// Note: this dummy function is defined so the non-dependent user function name will always resolve to something;
// some compilers will throw an error if the name doesn't resolve.
void adaptorF_custom_convertToStdVector(void* dont_use) {
inline void adaptorF_custom_convertToStdVector(void* dont_use) {
// dummy function
}

// Highest priority: user-specified function
template <class T, class S,
/* condition: user defined function exists and returns something that can be bracked-indexed to get an S */
/* condition: user defined function exists and returns something that can be bracket-indexed to get an S */
typename C1 = typename std::enable_if< std::is_same<decltype((S)adaptorF_custom_convertToStdVector(*(T*)nullptr)[0]), S>::value>::type>

std::vector<S> adaptorF_convertToStdVectorImpl(PreferenceT<4>, const T& inputData) {
Expand Down Expand Up @@ -351,7 +354,7 @@ std::vector<S> adaptorF_convertToStdVector(const T& inputData) {

// Note: this dummy function is defined so the non-dependent user function name will always resolve to something;
// some compilers will throw an error if the name doesn't resolve.
void adaptorF_custom_accessVector2Value(void* dont_use) {
inline void adaptorF_custom_accessVector2Value(void* dont_use) {
// dummy function
}

Expand Down Expand Up @@ -466,7 +469,7 @@ S adaptorF_accessVector2Value(const T& inVal) {

// Note: this dummy function is defined so the non-dependent user function name will always resolve to something;
// some compilers will throw an error if the name doesn't resolve.
void adaptorF_custom_accessVector3Value(void* dont_use) {
inline void adaptorF_custom_accessVector3Value(void* dont_use) {
// dummy function
}

Expand Down Expand Up @@ -566,7 +569,7 @@ S adaptorF_accessVector3Value(const T& inVal) {

// Note: this dummy function is defined so the non-dependent user function name will always resolve to something;
// some compilers will throw an error if the name doesn't resolve.
void adaptorF_custom_convertArrayOfVectorToStdVector(void* dont_use) {
inline void adaptorF_custom_convertArrayOfVectorToStdVector(void* dont_use) {
// dummy function
}

Expand Down Expand Up @@ -634,7 +637,7 @@ std::vector<O> adaptorF_convertArrayOfVectorToStdVectorImpl(PreferenceT<6>, cons

// Next: bracketed array of anything adaptable to vector3
template <class O, unsigned int D, class T,
/* helper type: inner type that results from bracked-indexing T */
/* helper type: inner type that results from bracket-indexing T */
typename C_INNER = typename std::remove_reference<decltype((*(T*)nullptr)[(size_t)0])>::type,
/* helper type: inner type of output O */
typename C_RES = typename InnerType<O>::type,
Expand All @@ -658,7 +661,7 @@ std::vector<O> adaptorF_convertArrayOfVectorToStdVectorImpl(PreferenceT<5>, cons

// Next: bracketed array of anything adaptable to vector2
template <class O, unsigned int D, class T,
/* helper type: inner type that results from bracked-indexing T */
/* helper type: inner type that results from bracket-indexing T */
typename C_INNER = typename std::remove_reference<decltype((*(T*)nullptr)[(size_t)0])>::type,
/* helper type: inner type of output O */
typename C_RES = typename InnerType<O>::type,
Expand Down Expand Up @@ -805,7 +808,7 @@ std::vector<O> adaptorF_convertArrayOfVectorToStdVector(const T& inputData) {

// Note: this dummy function is defined so the non-dependent name adaptorF_custom_convertArrayOfVectorToStdVector will
// always resolve to something; some compilers will throw an error if the name doesn't resolve.
void adaptorF_custom_convertNestedArrayToStdVector(void* dont_use) {
inline void adaptorF_custom_convertNestedArrayToStdVector(void* dont_use) {
// dummy function
}

Expand Down Expand Up @@ -1019,7 +1022,7 @@ std::vector<D> standardizeArray(const T& inputData) {
}

// Convert an array of vector types
// class O: output inner vector type to put the result in. Will be bracked-indexed.
// class O: output inner vector type to put the result in. Will be bracket-indexed.
// (Polyscope pretty much always uses glm::vec2/3, std::vector<>, or std::array<>)
// unsigned int D: dimension of inner vector type
// class T: input array type
Expand Down
2 changes: 1 addition & 1 deletion include/polyscope/surface_mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ inline SurfaceMesh* getSurfaceMesh(std::string name = "") {
// Implementation of templated constructor
template <class V, class F>
SurfaceMesh::SurfaceMesh(std::string name, const V& vertexPositions, const F& faceIndices)
: QuantityStructure<SurfaceMesh>(name), vertices(standardizeVectorArray<glm::vec3, V, 3>(vertexPositions)),
: QuantityStructure<SurfaceMesh>(name), vertices(standardizeVectorArray<glm::vec3, 3>(vertexPositions)),
faces(standardizeNestedList<size_t, F>(faceIndices)) {

computeCounts();
Expand Down
22 changes: 11 additions & 11 deletions include/polyscope/surface_mesh.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ void SurfaceMesh::setAllPermutations(const std::array<std::pair<T, size_t>, 5>&
template <class T>
SurfaceVertexColorQuantity* SurfaceMesh::addVertexColorQuantity(std::string name, const T& colors) {
validateSize<T>(colors, vertexDataSize, "vertex color quantity " + name);
return addVertexColorQuantityImpl(name, standardizeVectorArray<glm::vec3, T, 3>(colors));
return addVertexColorQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(colors));
}


template <class T>
SurfaceFaceColorQuantity* SurfaceMesh::addFaceColorQuantity(std::string name, const T& colors) {
validateSize<T>(colors, faceDataSize, "face color quantity " + name);
return addFaceColorQuantityImpl(name, standardizeVectorArray<glm::vec3, T, 3>(colors));
return addFaceColorQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(colors));
}


Expand Down Expand Up @@ -163,8 +163,8 @@ SurfaceDistanceQuantity* SurfaceMesh::addVertexSignedDistanceQuantity(std::strin

template <class P, class E>
SurfaceGraphQuantity* SurfaceMesh::addSurfaceGraphQuantity(std::string name, const P& nodes, const E& edges) {
return addSurfaceGraphQuantityImpl(name, standardizeVectorArray<glm::vec3, P, 3>(nodes),
standardizeVectorArray<std::array<size_t, 2>, E, 2>(edges));
return addSurfaceGraphQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(nodes),
standardizeVectorArray<std::array<size_t, 2>, 2>(edges));
}


Expand All @@ -173,23 +173,23 @@ template <class T>
SurfaceCornerParameterizationQuantity* SurfaceMesh::addParameterizationQuantity(std::string name, const T& coords,
ParamCoordsType type) {
validateSize(coords, cornerDataSize, "parameterization quantity " + name);
return addParameterizationQuantityImpl(name, standardizeVectorArray<glm::vec2, T, 2>(coords), type);
return addParameterizationQuantityImpl(name, standardizeVectorArray<glm::vec2, 2>(coords), type);
}

// Parameterization defined at vertices, rather than corners
template <class T>
SurfaceVertexParameterizationQuantity* SurfaceMesh::addVertexParameterizationQuantity(std::string name, const T& coords,
ParamCoordsType type) {
validateSize(coords, vertexDataSize, "parameterization (at vertices) quantity " + name);
return addVertexParameterizationQuantityImpl(name, standardizeVectorArray<glm::vec2, T, 2>(coords), type);
return addVertexParameterizationQuantityImpl(name, standardizeVectorArray<glm::vec2, 2>(coords), type);
}

// "local" parameterization defined at vertices. has different presets: type is WORLD and style is LOCAL
template <class T>
SurfaceVertexParameterizationQuantity* SurfaceMesh::addLocalParameterizationQuantity(std::string name, const T& coords,
ParamCoordsType type) {
validateSize(coords, vertexDataSize, "parameterization (at vertices) quantity " + name);
return addLocalParameterizationQuantityImpl(name, standardizeVectorArray<glm::vec2, T, 2>(coords), type);
return addLocalParameterizationQuantityImpl(name, standardizeVectorArray<glm::vec2, 2>(coords), type);
}


Expand Down Expand Up @@ -222,29 +222,29 @@ template <class T>
SurfaceVertexVectorQuantity* SurfaceMesh::addVertexVectorQuantity(std::string name, const T& vectors,
VectorType vectorType) {
validateSize(vectors, vertexDataSize, "vertex vector quantity " + name);
return addVertexVectorQuantityImpl(name, standardizeVectorArray<glm::vec3, T, 3>(vectors), vectorType);
return addVertexVectorQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(vectors), vectorType);
}

template <class T>
SurfaceFaceVectorQuantity* SurfaceMesh::addFaceVectorQuantity(std::string name, const T& vectors,
VectorType vectorType) {
validateSize(vectors, faceDataSize, "face vector quantity " + name);
return addFaceVectorQuantityImpl(name, standardizeVectorArray<glm::vec3, T, 3>(vectors), vectorType);
return addFaceVectorQuantityImpl(name, standardizeVectorArray<glm::vec3, 3>(vectors), vectorType);
}

template <class T>
SurfaceFaceIntrinsicVectorQuantity* SurfaceMesh::addFaceIntrinsicVectorQuantity(std::string name, const T& vectors,
int nSym, VectorType vectorType) {
validateSize(vectors, faceDataSize, "face intrinsic vector quantity " + name);
return addFaceIntrinsicVectorQuantityImpl(name, standardizeVectorArray<glm::vec2, T, 2>(vectors), nSym, vectorType);
return addFaceIntrinsicVectorQuantityImpl(name, standardizeVectorArray<glm::vec2, 2>(vectors), nSym, vectorType);
}


template <class T>
SurfaceVertexIntrinsicVectorQuantity* SurfaceMesh::addVertexIntrinsicVectorQuantity(std::string name, const T& vectors,
int nSym, VectorType vectorType) {
validateSize(vectors, vertexDataSize, "vertex intrinsic vector quantity " + name);
return addVertexIntrinsicVectorQuantityImpl(name, standardizeVectorArray<glm::vec2, T, 2>(vectors), nSym, vectorType);
return addVertexIntrinsicVectorQuantityImpl(name, standardizeVectorArray<glm::vec2, 2>(vectors), nSym, vectorType);
}

// Orientations is `true` if the canonical orientation of the edge points from the lower-indexed vertex to the
Expand Down

0 comments on commit b1d2e9f

Please sign in to comment.