diff --git a/include/geometrycentral/surface/surface_point.h b/include/geometrycentral/surface/surface_point.h index 0480fbc2..5fcdef49 100644 --- a/include/geometrycentral/surface/surface_point.h +++ b/include/geometrycentral/surface/surface_point.h @@ -55,6 +55,9 @@ struct SurfacePoint { // Return the nearest vertex to this surface point inline Vertex nearestVertex() const; + // Return the equivalent surface point in the 'reduced' form (can be seen as the inverse of inSomeFace). + // An edge point may be reduced to a vertex point, and a face point may be reduced to an edge point or a vertex point. + inline SurfacePoint reduced() const; // Linearly interpolate data at vertices to this point. // T must support addition and multiplication by a double. diff --git a/include/geometrycentral/surface/surface_point.ipp b/include/geometrycentral/surface/surface_point.ipp index 520bef5b..a84f336e 100644 --- a/include/geometrycentral/surface/surface_point.ipp +++ b/include/geometrycentral/surface/surface_point.ipp @@ -176,6 +176,42 @@ inline Vertex SurfacePoint::nearestVertex() const { return vertex; } +inline SurfacePoint SurfacePoint::reduced() const { + switch (type) { + case SurfacePointType::Vertex: { + return *this; + } + case SurfacePointType::Edge: { + if (tEdge == 0. || tEdge == 1.) + return SurfacePoint(nearestVertex()); + else + return *this; + } + case SurfacePointType::Face: { + if (faceCoords.x == 1. || faceCoords.y == 1. || faceCoords.z == 1.) + return SurfacePoint(nearestVertex()); + else if (faceCoords.z == 0.) { + Edge e = face.halfedge().edge(); + double tEdge = face == e.halfedge().face() ? faceCoords.y : faceCoords.x; + return SurfacePoint(e, tEdge); + } else if (faceCoords.x == 0.) { + Edge e = face.halfedge().next().edge(); + double tEdge = face == e.halfedge().face() ? faceCoords.z : faceCoords.y; + return SurfacePoint(e, tEdge); + } else if (faceCoords.y == 0.) { + Edge e = face.halfedge().next().next().edge(); + double tEdge = face == e.halfedge().face() ? faceCoords.x : faceCoords.z; + return SurfacePoint(e, tEdge); + } else { + return *this; + } + } + } + + throw std::logic_error("bad switch"); + return {}; +} + template inline T SurfacePoint::interpolate(const VertexData& data) const {