Skip to content

File TopologicMesh.h

File List > include > mesh > TopologicMesh.h

Go to the documentation of this file

#pragma once

#include "Mesh.h"
#include "Vector3D.h"
#include <map>
#include <unordered_map>
#include <vector>

namespace Argos {

class EdgeInfo {
public:
  int VertexAInd; 
  int VertexBInd; 
  EdgeInfo(int vertexAInd, int vertexBInd);
};

class FaceInfo {
public:
  std::vector<EdgeInfo> edges; 
  FaceInfo(std::vector<EdgeInfo> edges);
};

class HoleInfo {
private:
  std::vector<Vector3D<double>> vertices;
public:
  HoleInfo(std::vector<Vector3D<double>> vertices);

  std::vector<Vector3D<double>> getVertices() const;

  double circumference() const;
};

template <typename Tag> struct IndexType {
  int value = -1; 
  IndexType() = default;
  explicit IndexType(int v) : value(v) {}

  operator int() const { return value; }
  bool operator==(IndexType o) const { return value == o.value; }
  bool operator!=(IndexType o) const { return value != o.value; }
  bool operator<(IndexType o) const { return value < o.value; }
  bool operator<=(IndexType o) const { return value <= o.value; }
  bool operator>(IndexType o) const { return value > o.value; }
  bool operator>=(IndexType o) const { return value >= o.value; }
  IndexType &operator++() {
    ++value;
    return *this;
  }
  IndexType operator++(int) {
    auto old = *this;
    ++*this;
    return old;
  }
};
using VtxIdx = IndexType<struct VtxIdxTag>;
using OrigVtxIdx = IndexType<struct OrigVtxIdxTag>;
using EdgeIdx = IndexType<struct EdgeIdxTag>;
using FaceIdx = IndexType<struct FaceIdxTag>;

class TopologicMesh {
private:
  std::vector<Vector3D<double>> vertices;

  std::vector<VtxIdx> edge_vertex_pairs;

  std::vector<EdgeIdx> face_edge_indices;
  std::vector<size_t> face_edge_offsets;

  std::vector<EdgeIdx> edge_neighbor_edges;
  std::vector<size_t> edge_neighbor_offsets;

  std::vector<size_t> edge_face_count;

  void _getEdgeVertices(EdgeIdx i, VtxIdx &a, VtxIdx &b) const;

  std::vector<EdgeIdx> _getAllBorderEdges() const;

  void _getEdgeNeighbors(EdgeIdx edgeIdx, std::vector<EdgeIdx> &out) const;

  void _deduplicateStructure(
      const std::vector<Vector3D<double>> &vertices,
      const std::vector<Face> &faces,
      std::unordered_map<Vector3D<double>, VtxIdx> &origPosToVtxIdx,
      std::map<VtxIdx, std::vector<EdgeIdx>> &vtxIdxToEdgeIndices,
      std::map<VtxIdx, std::vector<FaceIdx>> &vtxIdxToFaceIndices);

  void _deduplicateVertex(
      OrigVtxIdx origVtxIdx, VtxIdx &vtxIdx, VtxIdx &nextVtxIdx,
      const std::vector<Vector3D<double>> &vertices,
      std::unordered_map<Vector3D<double>, VtxIdx> &origPosToVtxIdx);

  EdgeIdx _findOrCreateEdge(
      VtxIdx vtxIdxA, VtxIdx vtxIdxB, EdgeIdx &nextEdgeIdx,
      std::map<VtxIdx, std::vector<EdgeIdx>> &vtxIdxToEdgeIndices);

  void
  _addFaceToVertex(VtxIdx vtxIdx, FaceIdx originFaceIdx,
                   std::map<VtxIdx, std::vector<FaceIdx>> &vtxIdxToFaceIndices);

  void _computeEdgeNeighbors(
      std::map<VtxIdx, std::vector<EdgeIdx>> &vtxIdxToEdgeIndices,
      std::map<VtxIdx, std::vector<FaceIdx>> &vtxIdxToFaceIndices);

public:
  TopologicMesh(std::vector<Vector3D<double>> vertices,
                std::vector<Face> faces);

  TopologicMesh(const Mesh &other);

  TopologicMesh &operator=(const Mesh &other);

  EdgeInfo getEdge(size_t edgeIndex) const;

  FaceInfo getFace(size_t faceIndex) const;

  bool isBorder(size_t edgeIndex) const;

  std::vector<int> getAllBorderEdges() const;

  std::vector<HoleInfo> findAllHoles() const;

  size_t vertexCount() const;

  size_t edgeCount() const;

  size_t faceCount() const;

  Vector3D<double> getVertex(size_t index) const;

  size_t edgeFaceCount(size_t edgeIndex);

  std::vector<int> getAdjacentEdges(size_t edgeIndex) const;

  const std::vector<Vector3D<double>> &getVertices() const;
};

} // namespace Argos