Lagrange
compute_facet_area.h
1/*
2 * Copyright 2017 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 <Eigen/Dense>
15#include <exception>
16
17#include <lagrange/Mesh.h>
18#include <lagrange/MeshTrait.h>
19#include <lagrange/common.h>
20#include <lagrange/legacy/inline.h>
21#include <lagrange/utils/range.h>
22
23namespace lagrange {
24namespace internal {
25
35template <typename MeshType>
36auto compute_triangle_areas(const MeshType& mesh) -> AttributeArrayOf<MeshType>
37{
38 using Scalar = typename MeshType::Scalar;
39 using Index = typename MeshType::Index;
40 using Vector = Eigen::Matrix<Scalar, 3, 1>;
41
42 const Index dim = mesh.get_dim();
43 const Index num_facets = mesh.get_num_facets();
44 const auto& vertices = mesh.get_vertices();
45 const auto& facets = mesh.get_facets();
46 AttributeArrayOf<MeshType> areas(num_facets, 1);
47
48 if (dim == 2) {
49 for (Index i = 0; i < num_facets; i++) {
50 const Index i0 = facets(i, 0);
51 const Index i1 = facets(i, 1);
52 const Index i2 = facets(i, 2);
53 Vector v0, v1, v2;
54 v0 << vertices(i0, 0), vertices(i0, 1), 0.0;
55 v1 << vertices(i1, 0), vertices(i1, 1), 0.0;
56 v2 << vertices(i2, 0), vertices(i2, 1), 0.0;
57 Vector e1 = v1 - v0;
58 Vector e2 = v2 - v0;
59 areas(i, 0) = Scalar(0.5) * (e1.cross(e2)).norm();
60 }
61 } else if (dim == 3) {
62 for (Index i = 0; i < num_facets; i++) {
63 const Index i0 = facets(i, 0);
64 const Index i1 = facets(i, 1);
65 const Index i2 = facets(i, 2);
66 Vector v0, v1, v2;
67 v0 << vertices(i0, 0), vertices(i0, 1), vertices(i0, 2);
68 v1 << vertices(i1, 0), vertices(i1, 1), vertices(i1, 2);
69 v2 << vertices(i2, 0), vertices(i2, 1), vertices(i2, 2);
70 Vector e1 = v1 - v0;
71 Vector e2 = v2 - v0;
72 areas(i, 0) = Scalar(0.5) * (e1.cross(e2)).norm();
73 }
74 } else {
75 throw std::runtime_error("Unsupported dimention.");
76 }
77
78 return areas;
79}
80
90template <typename MeshType>
91auto compute_quad_areas(const MeshType& mesh) -> AttributeArrayOf<MeshType>
92{
93 using Scalar = typename MeshType::Scalar;
94 using Index = typename MeshType::Index;
95 using Vector = Eigen::Matrix<Scalar, 3, 1>;
96
97 const Index dim = mesh.get_dim();
98 const Index num_facets = mesh.get_num_facets();
99 const auto& vertices = mesh.get_vertices();
100 const auto& facets = mesh.get_facets();
101 AttributeArrayOf<MeshType> areas(num_facets, 1);
102
103 if (dim == 2) {
104 for (Index i = 0; i < num_facets; i++) {
105 const Index i0 = facets(i, 0);
106 const Index i1 = facets(i, 1);
107 const Index i2 = facets(i, 2);
108 const Index i3 = facets(i, 3);
109 Vector v0, v1, v2, v3;
110 v0 << vertices(i0, 0), vertices(i0, 1), 0.0f;
111 v1 << vertices(i1, 0), vertices(i1, 1), 0.0f;
112 v2 << vertices(i2, 0), vertices(i2, 1), 0.0f;
113 v3 << vertices(i3, 0), vertices(i3, 1), 0.0f;
114 Vector e10 = v1 - v0;
115 Vector e30 = v3 - v0;
116 Vector e12 = v1 - v2;
117 Vector e32 = v3 - v2;
118 areas(i, 0) = 0.5f * (e10.cross(e30)).norm() + 0.5f * (e12.cross(e32)).norm();
119 }
120 } else if (dim == 3) {
121 for (Index i = 0; i < num_facets; i++) {
122 const Index i0 = facets(i, 0);
123 const Index i1 = facets(i, 1);
124 const Index i2 = facets(i, 2);
125 const Index i3 = facets(i, 3);
126 Vector v0, v1, v2, v3;
127 v0 << vertices(i0, 0), vertices(i0, 1), vertices(i0, 2);
128 v1 << vertices(i1, 0), vertices(i1, 1), vertices(i1, 2);
129 v2 << vertices(i2, 0), vertices(i2, 1), vertices(i2, 2);
130 v3 << vertices(i3, 0), vertices(i3, 1), vertices(i3, 2);
131 Vector e10 = v1 - v0;
132 Vector e30 = v3 - v0;
133 Vector e12 = v1 - v2;
134 Vector e32 = v3 - v2;
135 areas(i, 0) = 0.5f * (e10.cross(e30)).norm() + 0.5f * (e12.cross(e32)).norm();
136 }
137 } else {
138 throw std::runtime_error("Unsupported dimention.");
139 }
140
141 return areas;
142}
143} // namespace internal
144
145LAGRANGE_LEGACY_INLINE
146namespace legacy {
147
157template <typename MeshType>
158auto compute_facet_area_raw(const MeshType& mesh) -> AttributeArrayOf<MeshType>
159{
160 static_assert(MeshTrait<MeshType>::is_mesh(), "Input type is not Mesh");
161 using Index = typename MeshType::Index;
162 const Index vertex_per_facet = mesh.get_vertex_per_facet();
163 if (vertex_per_facet == 3) {
165 } else if (vertex_per_facet == 4) {
166 return internal::compute_quad_areas(mesh);
167 } else {
168 throw std::runtime_error("Unsupported facet type.");
169 }
170}
171
179template <typename MeshType>
181{
182 static_assert(MeshTrait<MeshType>::is_mesh(), "Input type is not Mesh");
183 auto areas = compute_facet_area_raw(mesh);
184 mesh.add_facet_attribute("area");
185 mesh.import_facet_attribute("area", areas);
186}
187
199template <typename DerivedUV, typename DerivedF>
200Eigen::Matrix<typename DerivedUV::Scalar, Eigen::Dynamic, 1> compute_uv_area_raw(
201 const Eigen::MatrixBase<DerivedUV>& uv,
202 const Eigen::MatrixBase<DerivedF>& triangles)
203{
204 using Scalar = typename DerivedUV::Scalar;
205 using Index = typename DerivedF::Scalar;
206
207 la_runtime_assert(uv.cols() == 2);
208 la_runtime_assert(triangles.cols() == 3);
209 const auto num_triangles = triangles.rows();
210
211 auto compute_single_triangle_area = [&uv, &triangles](Index i) {
212 const auto& f = triangles.row(i);
213 const auto& v0 = uv.row(f[0]);
214 const auto& v1 = uv.row(f[1]);
215 const auto& v2 = uv.row(f[2]);
216 return 0.5f * (v0[0] * v1[1] + v1[0] * v2[1] + v2[0] * v0[1] - v0[0] * v2[1] -
217 v1[0] * v0[1] - v2[0] * v1[1]);
218 };
219
220 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> areas(num_triangles);
221 for (auto i : range(safe_cast<Index>(num_triangles))) {
222 areas[i] = compute_single_triangle_area(i);
223 }
224 return areas;
225}
226} // namespace legacy
227} // namespace lagrange
Definition: Mesh.h:48
AttributeId compute_facet_area(SurfaceMesh< Scalar, Index > &mesh, FacetAreaOptions options={})
Compute per-facet area.
Definition: compute_area.cpp:304
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
Type alias for one-dimensional column Eigen vectors.
Definition: views.h:79
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition: range.h:176
auto compute_quad_areas(const MeshType &mesh) -> AttributeArrayOf< MeshType >
Calculates the quad areas.
Definition: compute_facet_area.h:91
auto compute_triangle_areas(const MeshType &mesh) -> AttributeArrayOf< MeshType >
Calculates the triangle areas.
Definition: compute_facet_area.h:36
Main namespace for Lagrange.
Definition: AABBIGL.h:30