Lagrange
Loading...
Searching...
No Matches
clipped_triangle_circumcenter.h
1/*
2 * Copyright 2024 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/utils/assert.h>
15
16#include <Eigen/Core>
17
18#include <cmath>
19#include <limits>
20
21namespace lagrange::internal {
22
28template <typename Scalar>
29Eigen::Vector3<Scalar> clipped_triangle_circumcenter(
30 const Eigen::Vector3<Scalar>& p1,
31 const Eigen::Vector3<Scalar>& p2,
32 const Eigen::Vector3<Scalar>& p3,
33 Scalar& lambda1,
34 Scalar& lambda2,
35 Scalar& lambda3)
36{
37 [[maybe_unused]] constexpr const Scalar epsilon = 1e-7f;
38
39 using Vec3 = Eigen::Vector3<Scalar>;
40
41 const Vec3 q2 = p2 - p1;
42 const Vec3 q3 = p3 - p1;
43
44 Scalar l2 = q2.squaredNorm();
45 Scalar l3 = q3.squaredNorm();
46
47 Scalar a12 = -2.0f * q2.dot(q2);
48 Scalar a13 = -2.0f * q3.dot(q2);
49 Scalar a22 = -2.0f * q2.dot(q3);
50 Scalar a23 = -2.0f * q3.dot(q3);
51
52 Scalar c31 = (a23 * a12 - a22 * a13);
53 Scalar d = c31;
54 if (std::abs(d) < std::numeric_limits<Scalar>::denorm_min()) {
55 // Degenerate (collinear) triangle: the circumcenter is undefined. Fall back to the
56 // triangle barycenter.
57 lambda1 = lambda2 = lambda3 = Scalar(1) / Scalar(3);
58 return lambda1 * p1 + lambda2 * p2 + lambda3 * p3;
59 }
60 Scalar s = 1.0f / d;
61 lambda1 = s * ((a23 - a22) * l2 + (a12 - a13) * l3 + c31);
62 lambda2 = s * ((-a23) * l2 + (a13)*l3);
63 lambda3 = s * ((a22)*l2 + (-a12) * l3);
64
65 if (lambda1 < 0) {
66 lambda1 = 0;
67 la_debug_assert(lambda2 >= 0);
68 la_debug_assert(lambda3 >= 0);
69 lambda2 = 0.5f;
70 lambda3 = 0.5f;
71 }
72
73 if (lambda2 < 0) {
74 lambda2 = 0;
75 la_debug_assert(lambda1 >= 0);
76 la_debug_assert(lambda3 >= 0);
77 lambda1 = 0.5f;
78 lambda3 = 0.5f;
79 }
80
81 if (lambda3 < 0) {
82 lambda3 = 0;
83 la_debug_assert(lambda1 >= 0);
84 la_debug_assert(lambda2 >= 0);
85 lambda1 = 0.5f;
86 lambda2 = 0.5f;
87 }
88
89 la_debug_assert(std::fabs(lambda1 + lambda2 + lambda3 - 1) < epsilon);
90 return lambda1 * p1 + lambda2 * p2 + lambda3 * p3;
91}
92
93} // namespace lagrange::internal
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
#define la_debug_assert(...)
Debug assertion check.
Definition assert.h:197
nullptr_t, size_t, ptrdiff_t basic_ostream bad_weak_ptr extent, remove_extent, is_array,...
Definition attribute_string_utils.h:21
Eigen::Vector3< Scalar > clipped_triangle_circumcenter(const Eigen::Vector3< Scalar > &p1, const Eigen::Vector3< Scalar > &p2, const Eigen::Vector3< Scalar > &p3, Scalar &lambda1, Scalar &lambda2, Scalar &lambda3)
Compute the circumcenter of a triangle (p1, p2, p3), clipped to the triangle if it lies outside.
Definition clipped_triangle_circumcenter.h:29