MySources/edgemesh.cpp

356 lines
12 KiB
C++
Raw Normal View History

2020-11-27 11:47:21 +01:00
#include "edgemesh.hpp"
#include "vcg/simplex/face/topology.h"
2021-03-15 18:04:29 +01:00
#include <wrap/nanoply/include/nanoplyWrapper.hpp>
2020-11-27 11:47:21 +01:00
Eigen::MatrixX2i VCGEdgeMesh::getEigenEdges() const { return eigenEdges; }
Eigen::MatrixX3d VCGEdgeMesh::getEigenVertices() const {
// getVertices(eigenVertices);
return eigenVertices;
}
Eigen::MatrixX3d VCGEdgeMesh::getEigenEdgeNormals() const {
return eigenEdgeNormals;
}
bool VCGEdgeMesh::savePly(const std::string plyFilename) {
unsigned int mask = 0;
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEINDEX;
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTNORMAL;
if (nanoply::NanoPlyWrapper<VCGEdgeMesh>::SaveModel(
plyFilename.c_str(), *this, mask, false) != 0) {
return false;
}
return true;
}
2020-11-27 11:47:21 +01:00
void VCGEdgeMesh::GeneratedRegularSquaredPattern(
const double angleDeg, std::vector<std::vector<vcg::Point2d>> &pattern,
const size_t &desiredNumberOfSamples) {
static const size_t piSamples = 10;
// generate a pattern in a 1x1 quad
const vcg::Point2d offset(0, 0);
const size_t samplesNo = desiredNumberOfSamples;
// std::max(desiredNumberOfSamples, size_t(piSamples * (angleDeg /
// 180)));
const double angle = vcg::math::ToRad(angleDeg);
pattern.clear();
// first arm
std::vector<vcg::Point2d> arm;
{
for (int k = 0; k <= samplesNo; k++) {
const double t = double(k) / samplesNo;
const double a = (1 - t) * angle;
2021-03-15 18:04:29 +01:00
// const double r = vcg::math::Sin(t*M_PI_2) /*(1-((1-t)*(1-t)))*/ *
// 0.5;
2020-11-27 11:47:21 +01:00
const double r = t * 0.5; // linear
vcg::Point2d p(vcg::math::Cos(a), vcg::math::Sin(a));
arm.push_back((p * r));
}
pattern.push_back(arm);
}
// other arms
for (int i = 0; i < 3; i++) {
for (vcg::Point2d &p : arm) {
p = vcg::Point2d(-p.Y(), p.X());
}
pattern.push_back(arm);
}
assert(pattern.size() == 4);
// offset all
for (auto &arm : pattern) {
for (vcg::Point2d &p : arm) {
p += offset;
}
}
}
void VCGEdgeMesh::createSpiral(const float &degreesOfArm,
const size_t &numberOfSamples) {
std::vector<std::vector<vcg::Point2d>> spiralPoints;
GeneratedRegularSquaredPattern(degreesOfArm, spiralPoints, numberOfSamples);
for (size_t armIndex = 0; armIndex < spiralPoints.size(); armIndex++) {
for (size_t pointIndex = 0; pointIndex < spiralPoints[armIndex].size() - 1;
pointIndex++) {
const vcg::Point2d p0 = spiralPoints[armIndex][pointIndex];
const vcg::Point2d p1 = spiralPoints[armIndex][pointIndex + 1];
CoordType n(0, 0, 1);
auto ei = vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(
*this, VCGEdgeMesh::CoordType(p0.X(), p0.Y(), 0),
VCGEdgeMesh::CoordType(p1.X(), p1.Y(), 0));
ei->cV(0)->N() = n;
ei->cV(1)->N() = n;
}
}
// setDefaultAttributes();
}
2020-12-03 19:56:03 +01:00
bool VCGEdgeMesh::createSpanGrid(const size_t squareGridDimension) {
return createSpanGrid(squareGridDimension, squareGridDimension);
2020-11-27 11:47:21 +01:00
}
2020-12-03 19:56:03 +01:00
bool VCGEdgeMesh::createSpanGrid(const size_t desiredWidth,
const size_t desiredHeight) {
2020-11-27 11:47:21 +01:00
std::cout << "Grid of dimensions:" << desiredWidth << "," << desiredHeight
<< std::endl;
const VCGEdgeMesh::CoordType n(0, 0, 1);
int x = 0;
int y = 0;
// for (size_t vi = 0; vi < numberOfVertices; vi++) {
while (y <= desiredHeight) {
// std::cout << x << " " << y << std::endl;
auto p = VCGEdgeMesh::CoordType(x, y, 0);
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(*this, p, n);
x++;
if (x > desiredWidth) {
x = 0;
y++;
}
}
for (size_t vi = 0; vi < VN(); vi++) {
int x = vi % (desiredWidth + 1);
int y = vi / (desiredWidth + 1);
const bool isCornerNode = (y == 0 && x == 0) ||
(y == 0 && x == desiredWidth) ||
(y == desiredHeight && x == 0) ||
(y == desiredHeight && x == desiredWidth);
if (isCornerNode) {
continue;
}
if (y == 0) { // row 0.Connect with node above
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi,
vi + desiredWidth + 1);
continue;
} else if (x == 0) { // col 0.Connect with node to the right
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi, vi + 1);
continue;
} else if (y == desiredHeight) { // row 0.Connect with node below
// vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi,
// vi - (desiredWidth +
// 1));
continue;
} else if (x == desiredWidth) { // row 0.Connect with node to the left
// vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi, vi - 1);
continue;
}
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi, vi + desiredWidth + 1);
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi, vi + 1);
// vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi,
// vi - (desiredWidth + 1));
// vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(*this, vi, vi - 1);
}
vcg::tri::Allocator<VCGEdgeMesh>::DeleteVertex(*this, vert[0]);
vcg::tri::Allocator<VCGEdgeMesh>::DeleteVertex(*this, vert[desiredWidth]);
vcg::tri::Allocator<VCGEdgeMesh>::DeleteVertex(
*this, vert[desiredHeight * (desiredWidth + 1)]);
vcg::tri::Allocator<VCGEdgeMesh>::DeleteVertex(
*this, vert[(desiredHeight + 1) * (desiredWidth + 1) - 1]);
vcg::tri::Allocator<VCGEdgeMesh>::CompactVertexVector(*this);
getEdges(eigenEdges);
getVertices(eigenVertices);
// vcg::tri::Allocator<VCGEdgeMesh>::CompactEdgeVector(*this);
// const size_t numberOfEdges =
// desiredHeight * (desiredWidth - 1) + desiredWidth * (desiredHeight -
// 1);
// handleBeamDimensions._handle->data.resize(
// numberOfEdges, CylindricalElementDimensions(0.03, 0.026));
// handleBeamMaterial._handle->data.resize(numberOfEdges,
// ElementMaterial(0.3, 200));
return true;
}
2021-03-15 18:04:29 +01:00
bool VCGEdgeMesh::load(const string &plyFilename) {
2020-11-27 11:47:21 +01:00
std::string usedPath = plyFilename;
if (std::filesystem::path(plyFilename).is_relative()) {
usedPath = std::filesystem::absolute(plyFilename).string();
}
assert(std::filesystem::exists(usedPath));
this->Clear();
2021-03-01 14:44:35 +01:00
if (!loadUsingNanoply(usedPath)) {
std::cerr << "Error: Unable to open " + usedPath << std::endl;
return false;
}
2020-11-27 11:47:21 +01:00
getEdges(eigenEdges);
getVertices(eigenVertices);
vcg::tri::UpdateTopology<VCGEdgeMesh>::VertexEdge(*this);
label = std::filesystem::path(plyFilename).stem().string();
2020-11-27 11:47:21 +01:00
2021-03-01 14:44:35 +01:00
const bool printDebugInfo = false;
if (printDebugInfo) {
std::cout << plyFilename << " was loaded successfuly." << std::endl;
std::cout << "Mesh has " << EN() << " edges." << std::endl;
}
2020-11-27 11:47:21 +01:00
return true;
}
bool VCGEdgeMesh::loadUsingNanoply(const std::string &plyFilename) {
this->Clear();
// assert(plyFileHasAllRequiredFields(plyFilename));
// Load the ply file
unsigned int mask = 0;
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTCOORD;
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_VERTNORMAL;
mask |= nanoply::NanoPlyWrapper<VCGEdgeMesh>::IO_EDGEINDEX;
2020-12-03 19:56:03 +01:00
if (nanoply::NanoPlyWrapper<VCGEdgeMesh>::LoadModel(plyFilename.c_str(),
*this, mask) != 0) {
2020-11-27 11:47:21 +01:00
return false;
}
return true;
}
2021-03-15 18:04:29 +01:00
// bool VCGEdgeMesh::plyFileHasAllRequiredFields(const std::string
// &plyFilename)
2020-12-03 19:56:03 +01:00
// {
// const nanoply::Info info(plyFilename);
// const std::vector<nanoply::PlyElement>::const_iterator edgeElemIt =
// std::find_if(info.elemVec.begin(), info.elemVec.end(),
// [&](const nanoply::PlyElement &plyElem) {
// return plyElem.plyElem == nanoply::NNP_EDGE_ELEM;
// });
// if (edgeElemIt == info.elemVec.end()) {
// std::cerr << "Ply file is missing edge elements." << std::endl;
// return false;
// }
// const std::vector<nanoply::PlyProperty> &edgePropertyVector =
// edgeElemIt->propVec;
// return hasPlyEdgeProperty(plyFilename, edgePropertyVector,
// plyPropertyBeamDimensionsID) &&
// hasPlyEdgeProperty(plyFilename, edgePropertyVector,
// plyPropertyBeamMaterialID);
//}
2020-11-27 11:47:21 +01:00
Eigen::MatrixX3d VCGEdgeMesh::getNormals() const {
Eigen::MatrixX3d vertexNormals;
vertexNormals.resize(VN(), 3);
for (int vertexIndex = 0; vertexIndex < VN(); vertexIndex++) {
VCGEdgeMesh::CoordType vertexNormal =
vert[static_cast<size_t>(vertexIndex)].cN();
vertexNormals.row(vertexIndex) =
vertexNormal.ToEigenVector<Eigen::Vector3d>();
}
return vertexNormals;
}
void VCGEdgeMesh::getEdges(Eigen::MatrixX3d &edgeStartingPoints,
Eigen::MatrixX3d &edgeEndingPoints) const {
edgeStartingPoints.resize(EN(), 3);
edgeEndingPoints.resize(EN(), 3);
for (int edgeIndex = 0; edgeIndex < EN(); edgeIndex++) {
const VCGEdgeMesh::EdgeType &edge = this->edge[edgeIndex];
edgeStartingPoints.row(edgeIndex) =
edge.cP(0).ToEigenVector<Eigen::Vector3d>();
edgeEndingPoints.row(edgeIndex) =
edge.cP(1).ToEigenVector<Eigen::Vector3d>();
}
}
2020-12-03 19:56:03 +01:00
VCGEdgeMesh::VCGEdgeMesh() {}
2020-11-27 11:47:21 +01:00
void VCGEdgeMesh::updateEigenEdgeAndVertices() {
2021-03-15 18:04:29 +01:00
#ifdef POLYSCOPE_DEFINED
2020-11-27 11:47:21 +01:00
getEdges(eigenEdges);
getVertices(eigenVertices);
2021-03-15 18:04:29 +01:00
#endif
2020-11-27 11:47:21 +01:00
}
void VCGEdgeMesh::copy(VCGEdgeMesh &mesh) {
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::MeshCopy(*this, mesh);
label = mesh.getLabel();
eigenEdges = mesh.getEigenEdges();
if (eigenEdges.rows() == 0) {
getEdges(eigenEdges);
}
eigenVertices = mesh.getEigenVertices();
if (eigenVertices.rows() == 0) {
getVertices(eigenVertices);
}
vcg::tri::UpdateTopology<VCGEdgeMesh>::VertexEdge(*this);
}
void VCGEdgeMesh::getVertices(Eigen::MatrixX3d &vertices) {
vertices = Eigen::MatrixX3d();
vertices.resize(VN(), 3);
for (int vi = 0; vi < VN(); vi++) {
if (vert[vi].IsD()) {
continue;
}
VCGEdgeMesh::CoordType vertexCoordinates =
vert[static_cast<size_t>(vi)].cP();
vertices.row(vi) = vertexCoordinates.ToEigenVector<Eigen::Vector3d>();
}
}
std::string VCGEdgeMesh::getLabel() const { return label; }
void VCGEdgeMesh::setLabel(const std::string &value) { label = value; }
void VCGEdgeMesh::getEdges(Eigen::MatrixX2i &edges) {
edges = Eigen::MatrixX2i();
edges.resize(EN(), 2);
for (int edgeIndex = 0; edgeIndex < EN(); edgeIndex++) {
const VCGEdgeMesh::EdgeType &edge = this->edge[edgeIndex];
2021-03-15 18:04:29 +01:00
assert(!edge.IsD());
auto vp0 = edge.cV(0);
auto vp1 = edge.cV(1);
assert(vcg::tri::IsValidPointer(*this, vp0) &&
vcg::tri::IsValidPointer(*this, vp1));
const size_t vi0 = vcg::tri::Index<VCGEdgeMesh>(*this, vp0);
const size_t vi1 = vcg::tri::Index<VCGEdgeMesh>(*this, vp1);
assert(vi0 != -1 && vi1 != -1);
edges.row(edgeIndex) = Eigen::Vector2i(vi0, vi1);
2020-11-27 11:47:21 +01:00
}
}
void VCGEdgeMesh::printVertexCoordinates(const size_t &vi) const {
std::cout << "vi:" << vi << " " << vert[vi].cP()[0] << " " << vert[vi].cP()[1]
<< " " << vert[vi].cP()[2] << std::endl;
}
2021-03-01 14:44:35 +01:00
#ifdef POLYSCOPE_DEFINED
void VCGEdgeMesh::registerForDrawing(
2021-03-15 18:04:29 +01:00
const std::optional<glm::vec3> &desiredColor,
const bool &shouldEnable) const {
2020-11-27 11:47:21 +01:00
initPolyscope();
2021-03-01 14:44:35 +01:00
const double drawingRadius = 0.002;
2021-03-15 18:04:29 +01:00
auto polyscopeHandle_edgeMesh = polyscope::registerCurveNetwork(
label, getEigenVertices(), getEigenEdges());
polyscopeHandle_edgeMesh->setEnabled(shouldEnable);
polyscopeHandle_edgeMesh->setRadius(drawingRadius, true);
2021-03-01 14:44:35 +01:00
if (desiredColor.has_value()) {
polyscopeHandle_edgeMesh->setColor(desiredColor.value());
}
}
void VCGEdgeMesh::unregister() const {
if (!polyscope::hasCurveNetwork(label)) {
std::cerr << "No curve network registered with a name: " << getLabel()
<< std::endl;
std::cerr << "Nothing to remove." << std::endl;
return;
}
polyscope::removeCurveNetwork(label);
2020-11-27 11:47:21 +01:00
}
2021-03-01 14:44:35 +01:00
#endif