Lagrange
sqrt_subdivision.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/Mesh.h>
15#include <lagrange/MeshTrait.h>
16#include <lagrange/create_mesh.h>
17#include <lagrange/legacy/inline.h>
18
19// clang-format off
20#include <lagrange/utils/warnoff.h>
21#include <igl/adjacency_list.h>
22#include <igl/barycenter.h>
23#include <igl/triangle_triangle_adjacency.h>
24#include <lagrange/utils/warnon.h>
25// clang-format on
26
27namespace lagrange {
28namespace subdivision {
29LAGRANGE_LEGACY_INLINE
30namespace legacy {
31
44template <typename DerivedVI, typename DerivedFI, typename DerivedVO, typename DerivedFO>
46 const Eigen::MatrixBase<DerivedVI>& VI,
47 const Eigen::MatrixBase<DerivedFI>& FI,
48 Eigen::PlainObjectBase<DerivedVO>& VO,
49 Eigen::PlainObjectBase<DerivedFO>& FO)
50{
51 using Scalar = typename DerivedVI::Scalar;
52 using Index = typename DerivedFI::Scalar;
53 using MatrixXs = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
54 using MatrixXi = Eigen::Matrix<Index, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
55 using RowVector3s = Eigen::Matrix<Scalar, 1, 3>;
56
57 // Step 1: new vertices at barycenter of every face
58 MatrixXs BC;
59 igl::barycenter(VI, FI, BC);
60
61 // Step 2: move old vertices to new positions
62 VO.resize(VI.rows() + FI.rows(), VI.cols());
63 VO.topRows(VI.rows()) = VI;
64 VO.bottomRows(BC.rows()) = BC;
65 std::vector<std::vector<Index>> VV;
66 igl::adjacency_list(FI, VV);
67 for (Index i = 0; i < (Index)VI.rows(); ++i) {
68 Scalar n = static_cast<Scalar>(VV[i].size());
69 Scalar an = static_cast<Scalar>((4.0 - 2.0 * std::cos(2.0 * M_PI / n)) / 9.0);
70 RowVector3s sum_vi = RowVector3s::Zero();
71 for (auto j : VV[i]) {
72 sum_vi += VI.row(j);
73 }
74 VO.row(i) = (1 - an) * VI.row(i) + an / n * sum_vi;
75 }
76
77 // Step 3: compute a new set of faces, and flip edges as required
78 FO.resize(3 * FI.rows(), FI.cols());
79 for (Index f = 0; f < (Index)FI.rows(); ++f) {
80 FO.row(3 * f + 0) << VI.rows() + f, FI(f, 0), FI(f, 1);
81 FO.row(3 * f + 1) << VI.rows() + f, FI(f, 1), FI(f, 2);
82 FO.row(3 * f + 2) << VI.rows() + f, FI(f, 2), FI(f, 0);
83 }
84 MatrixXi TT, TTi;
85 igl::triangle_triangle_adjacency(FI, TT, TTi);
86 for (Index f = 0; f < (Index)FI.rows(); ++f) {
87 for (Index i = 0; i < (Index)FI.cols(); ++i) {
88 if (TT(f, i) != static_cast<Index>(-1) && TT(f, i) > f) {
89 Index g = TT(f, i);
90 Index j = TTi(f, i);
91 FO(3 * f + i, 2) = VI.rows() + g;
92 FO(3 * g + j, 2) = VI.rows() + f;
93 }
94 }
95 }
96}
97
113template <
114 typename MeshType,
115 std::enable_if_t<lagrange::MeshTraitHelper::is_mesh<MeshType>::value>* = nullptr>
116std::unique_ptr<MeshType> sqrt_subdivision(const MeshType& mesh)
117{
118 static_assert(MeshTrait<MeshType>::is_mesh(), "Input type is not Mesh");
119
120 using VertexArray = typename MeshType::VertexArray;
121 using FacetArray = typename MeshType::FacetArray;
122
123 VertexArray V;
124 FacetArray F;
125 sqrt_subdivision(mesh.get_vertices(), mesh.get_facets(), V, F);
126 return lagrange::create_mesh(V, F);
127}
128
129} // namespace legacy
130} // namespace subdivision
131} // namespace lagrange
Definition: Mesh.h:48
SurfaceMesh< Scalar, Index > sqrt_subdivision(const SurfaceMesh< Scalar, Index > &mesh)
Performs one step of sqrt(3)-subdivision.
Definition: sqrt_subdivision.cpp:101
Main namespace for Lagrange.
Definition: AABBIGL.h:30
auto create_mesh(const Eigen::MatrixBase< DerivedV > &vertices, const Eigen::MatrixBase< DerivedF > &facets)
This function create a new mesh given the vertex and facet arrays by copying data into the Mesh objec...
Definition: create_mesh.h:39