Lagrange
geometry3d.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 <Eigen/Dense>
15#include <lagrange/MeshTrait.h>
16
17namespace lagrange {
18
22template <typename Scalar, int _Rows, int _Cols>
24 const Eigen::Matrix<Scalar, _Rows, _Cols>& v1,
25 const Eigen::Matrix<Scalar, _Rows, _Cols>& v2)
26{
27 static_assert((_Rows == 1 && _Cols == 3) || (_Rows == 3 && _Cols == 1), "");
28 Scalar dot = v1.dot(v2);
29 if (dot < -1) return Scalar(-1.0);
30 if (dot > 1) return Scalar(1.0);
31 return dot;
32}
33
35template <typename Scalar, int _Rows, int _Cols>
37 const Eigen::Matrix<Scalar, _Rows, _Cols>& v1,
38 const Eigen::Matrix<Scalar, _Rows, _Cols>& v2)
39{
40 static_assert((_Rows == 1 && _Cols == 3) || (_Rows == 3 && _Cols == 1), "");
41 return std::atan2(v1.cross(v2).norm(), v1.dot(v2));
42}
43
47template <typename Scalar, int _Rows, int _Cols>
48Eigen::Matrix<Scalar, _Rows, _Cols> project_on_line(
49 const Eigen::Matrix<Scalar, _Rows, _Cols>& v1,
50 const Eigen::Matrix<Scalar, _Rows, _Cols>& v2)
51{
52 static_assert((_Rows == 1 && _Cols == 3) || (_Rows == 3 && _Cols == 1), "");
53 return v1.dot(v2) * v2;
54}
55
58template <typename Scalar, int _Rows, int _Cols>
59Eigen::Matrix<Scalar, _Rows, _Cols> project_on_plane(
60 const Eigen::Matrix<Scalar, _Rows, _Cols>& v,
61 const Eigen::Matrix<Scalar, _Rows, _Cols>& n)
62{
63 static_assert((_Rows == 1 && _Cols == 3) || (_Rows == 3 && _Cols == 1), "");
64 return v - project_on_line(v, n);
65}
66
69template <typename Scalar, int _Rows, int _Cols>
71 const Eigen::Matrix<Scalar, _Rows, _Cols>& v1,
72 const Eigen::Matrix<Scalar, _Rows, _Cols>& v2,
73 const Eigen::Matrix<Scalar, _Rows, _Cols>& n)
74{
75 static_assert((_Rows == 1 && _Cols == 3) || (_Rows == 3 && _Cols == 1), "");
76 const Eigen::Matrix<Scalar, _Rows, _Cols> proj1 = project_on_plane(v1, n).stableNormalized();
77 const Eigen::Matrix<Scalar, _Rows, _Cols> proj2 = project_on_plane(v2, n).stableNormalized();
78 return cos_angle_between(proj1, proj2);
79}
80
83template <typename Scalar, int _Rows, int _Cols>
85 const Eigen::Matrix<Scalar, _Rows, _Cols>& v1,
86 const Eigen::Matrix<Scalar, _Rows, _Cols>& v2,
87 const Eigen::Matrix<Scalar, _Rows, _Cols>& n)
88{
89 static_assert((_Rows == 1 && _Cols == 3) || (_Rows == 3 && _Cols == 1), "");
90 const Eigen::Matrix<Scalar, _Rows, _Cols> proj1 = project_on_plane(v1, n);
91 const Eigen::Matrix<Scalar, _Rows, _Cols> proj2 = project_on_plane(v2, n);
92 return std::atan2(proj1.cross(proj2).norm(), proj1.dot(proj2));
93}
94
103template <typename MeshType>
104auto vector_between(const MeshType& mesh, typename MeshType::Index v1, typename MeshType::Index v2)
105{
106 static_assert(MeshTrait<MeshType>::is_mesh(), "MeshType is not a mesh");
107 return mesh.get_vertices().row(v2) - mesh.get_vertices().row(v1);
108}
109
119template <typename Scalar>
121 const Eigen::Matrix<Scalar, 3, 1>& x,
122 Eigen::Matrix<Scalar, 3, 1>& y,
123 Eigen::Matrix<Scalar, 3, 1>& z)
124{
125 int imin;
126 x.array().abs().minCoeff(&imin);
127 Eigen::Matrix<Scalar, 3, 1> u;
128 for (int i = 0, s = -1; i < 3; ++i) {
129 if (i == imin) {
130 u[i] = 0;
131 } else {
132 int j = (i + 1) % 3;
133 if (j == imin) {
134 j = (i + 2) % 3;
135 }
136 u[i] = s * x[j];
137 s *= -1;
138 }
139 }
140 z = x.cross(u).stableNormalized();
141 y = z.cross(x).stableNormalized();
142}
143
144} // namespace lagrange
Definition: Mesh.h:48
Main namespace for Lagrange.
Definition: AABBIGL.h:30
void orthogonal_frame(const Eigen::Matrix< Scalar, 3, 1 > &x, Eigen::Matrix< Scalar, 3, 1 > &y, Eigen::Matrix< Scalar, 3, 1 > &z)
Build an orthogonal frame given a single vector.
Definition: geometry3d.h:120
Scalar projected_cos_angle_between(const Eigen::Matrix< Scalar, _Rows, _Cols > &v1, const Eigen::Matrix< Scalar, _Rows, _Cols > &v2, const Eigen::Matrix< Scalar, _Rows, _Cols > &n)
Returns the angle between the vectors v1 and v2 projected on the plane defined by its normal n.
Definition: geometry3d.h:70
Scalar projected_angle_between(const Eigen::Matrix< Scalar, _Rows, _Cols > &v1, const Eigen::Matrix< Scalar, _Rows, _Cols > &v2, const Eigen::Matrix< Scalar, _Rows, _Cols > &n)
Returns the angle between the vectors v1 and v2 projected on the plane defined by its normal n.
Definition: geometry3d.h:84
Eigen::Matrix< Scalar, _Rows, _Cols > project_on_plane(const Eigen::Matrix< Scalar, _Rows, _Cols > &v, const Eigen::Matrix< Scalar, _Rows, _Cols > &n)
Project the vector on the plane defined by its normal n.
Definition: geometry3d.h:59
auto vector_between(const MeshType &mesh, typename MeshType::Index v1, typename MeshType::Index v2)
Returns the vector from v1 to v2.
Definition: geometry3d.h:104
Eigen::Matrix< Scalar, _Rows, _Cols > project_on_line(const Eigen::Matrix< Scalar, _Rows, _Cols > &v1, const Eigen::Matrix< Scalar, _Rows, _Cols > &v2)
Project the vector v1 on the line defined by its vector v2.
Definition: geometry3d.h:48
Scalar cos_angle_between(const Eigen::Matrix< Scalar, _Rows, _Cols > &v1, const Eigen::Matrix< Scalar, _Rows, _Cols > &v2)
Returns the cosine of the angle between two 3d vectors.
Definition: geometry3d.h:23
Scalar angle_between(const Eigen::Matrix< Scalar, _Rows, _Cols > &v1, const Eigen::Matrix< Scalar, _Rows, _Cols > &v2)
Returns the angle between two 3d vectors.
Definition: geometry3d.h:36
MeshTrait class provide compiler check for different mesh types.
Definition: MeshTrait.h:108