22#ifndef MESHKIT_NATIVE_MESHQUADQUALITY_HPP
23#define MESHKIT_NATIVE_MESHQUADQUALITY_HPP
77 double xScale = 0.0, yScale = 0.0;
78 for (
int i = 0;
i < 4; ++
i) {
79 if (!std::isfinite(
p[
i].
x()) || !std::isfinite(
p[
i].
y()))
82 if (!std::isfinite(local[
i].
x()) || !std::isfinite(local[
i].
y()))
84 xScale = std::max(xScale, std::abs(local[
i].
x()));
85 yScale = std::max(yScale, std::abs(local[
i].
y()));
87 if (!(xScale > 0.0) || !(yScale > 0.0))
91 const auto areaCross = [&](
int i,
int j) {
92 return (local[
i].
x() / xScale) * (local[j].
y() / yScale) -
93 (local[
i].
y() / yScale) * (local[j].
x() / xScale);
95 const double area2 = areaCross(1, 2) + areaCross(2, 3);
96 if (area2 == 0.0 || !std::isfinite(area2))
98 const double orient = area2 > 0.0 ? 1.0 : -1.0;
101 int areaExponent = 0, xExponent = 0, yExponent = 0;
102 const double areaMantissa = std::frexp(std::abs(area2), &areaExponent);
103 const double xMantissa = std::frexp(xScale, &xExponent);
104 const double yMantissa = std::frexp(yScale, &yExponent);
106 std::scalbn(areaMantissa * xMantissa * yMantissa, areaExponent + xExponent + yExponent - 1);
107 if (!(q.
area > 0.0) || !std::isfinite(q.
area))
116 for (
int i = 0;
i < 4; ++
i) {
117 const Point2 e1 =
p[(
i + 3) % 4] -
p[
i], e2 =
p[(
i + 1) % 4] -
p[
i];
118 const double l1 = std::hypot(e1.
x(), e1.
y()), l2 = std::hypot(e2.x(), e2.y());
119 if (!(l1 > 0.0) || !(l2 > 0.0) || !std::isfinite(l1) || !std::isfinite(l2))
122 const Point2 u1 = e1 / l1, u2 = e2 / l2;
125 const double cross = std::clamp(u2.x() * u1.
y() - u2.y() * u1.
x(), -1.0, 1.0);
126 const double dot = std::clamp(u1.
x() * u2.x() + u1.
y() * u2.y(), -1.0, 1.0);
127 const double ang = std::atan2(std::abs(cross), dot) * 180.0 /
pi;
128 const double sj = cross * orient;
134 maxDev = std::max(maxDev, std::abs(ang - 90.0));
137 const double s02 = 0.5 * side[0] + 0.5 * side[2];
138 const double s13 = 0.5 * side[1] + 0.5 * side[3];
139 const double lo = std::min(s02, s13), hi = std::max(s02, s13);
143 if (!std::isfinite(q.
aspect))
146 const double ld1 = std::hypot(d1.
x(), d1.
y()), ld2 = std::hypot(d2.x(), d2.y());
147 if (!(ld1 > 0.0) || !(ld2 > 0.0) || !std::isfinite(ld1) || !std::isfinite(ld2))
149 const Point2 ud1 = d1 / ld1, ud2 = d2 / ld2;
150 q.
skew = std::clamp(std::abs(ud1.
x() * ud2.x() + ud1.
y() * ud2.y()), 0.0, 1.0);
168 return quadQuality(vertices[
t.v0].xy, vertices[
t.v1].xy, vertices[
t.v2].xy, vertices[
t.v3].xy);
171namespace quadquality_detail
202 return std::isfinite(
b.minAngleDeg) && std::isfinite(
b.maxAngleDeg) &&
203 std::isfinite(
b.minScaledJacobian) && std::isfinite(
b.maxAspect);
228 if (
b.maxAspect > 0.0 && q.
aspect >
b.maxAspect)
251 const double aspectTerm =
252 (
b.maxAspect > 0.0 && q.
aspect >
b.maxAspect) ?
b.maxAspect / q.
aspect : 1.0;
275 double area2 = (
b.x() -
a.x()) * (
c.y() -
a.y()) - (
c.x() -
a.x()) * (
b.y() -
a.y());
276 const double orient = area2 >= 0.0 ? 1.0 : -1.0;
277 for (
int i = 0;
i < 3; ++
i) {
278 const Point2 e1 =
p[(
i + 2) % 3] -
p[
i], e2 =
p[(
i + 1) % 3] -
p[
i];
279 const double l1 = std::hypot(e1.
x(), e1.
y()), l2 = std::hypot(e2.x(), e2.y());
280 if (l1 <= 0.0 || l2 <= 0.0)
282 mn = std::min(mn, (e2.x() * e1.
y() - e2.y() * e1.
x()) * orient / (l1 * l2));
284 return std::min(mn, 1.0);
300 const int n =
t.vertexCount();
301 const Point2 &prev = v[
t.vertex((
i +
n - 1) %
n)].xy;
302 const Point2 &cur = v[
t.vertex(
i)].xy;
303 const Point2 &next = v[
t.vertex((
i + 1) %
n)].xy;
304 const Point2 e1 = prev - cur, e2 = next - cur;
305 return std::atan2(std::abs(e2.x() * e1.
y() - e2.y() * e1.
x()),
306 e1.
x() * e2.x() + e1.
y() * e2.y()) *
Definition geometry.hpp:11
constexpr double y() const noexcept
Definition geometry.hpp:18
constexpr double x() const noexcept
Definition geometry.hpp:17
Definition storage.hpp:18
size_t i
Definition contourjob.cpp:30
DiagramType t
Definition diagramspec.cpp:23
ArrowPlacement p
Definition linesymbollayer.cpp:29
bool finiteBounds(const QuadQualityBounds &b)
Check every supplied quality threshold is finite.
Definition quadquality.hpp:200
bool validMetrics(const QuadQuality &q)
Check the internal finite/range/convexity invariants required before acceptance or scoring.
Definition quadquality.hpp:182
QuadQuality quadQuality(const Point2 &a, const Point2 &b, const Point2 &c, const Point2 &d)
Measure one quadrilateral using cyclic corners and translation/scale-resistant planar arithmetic.
Definition quadquality.hpp:72
constexpr double pi
Definition planmodel.hpp:12
double triangleScaledJacobian(const Point2 &a, const Point2 &b, const Point2 &c)
Compute the minimum orientation-normalized corner sine of a triangle.
Definition quadquality.hpp:271
bool quadAcceptable(const QuadQuality &q, const QuadQualityBounds &b)
Apply inclusive hard angle/Jacobian/aspect limits to a valid convex metric record.
Definition quadquality.hpp:220
double cellCornerAngleDeg(const Vector< MeshVertex > &v, const MeshTriangle &t, int i)
Compute the unsigned corner angle of a triangle or quad.
Definition quadquality.hpp:298
double quadScore(const QuadQuality &q, const QuadQualityBounds &b)
Rank valid convex quads by Jacobian, rectangularity and a soft aspect penalty.
Definition quadquality.hpp:247
Definition planmodel.hpp:78
Acceptance bounds shared by pairing, cleanup, smoothing and the legacy tri-pair merge....
Definition quadquality.hpp:35
double minScaledJacobian
Definition quadquality.hpp:38
double maxAngleDeg
Definition quadquality.hpp:37
double maxAspect
longest / shortest side (opposite-side means). <= 0 = unbounded.
Definition quadquality.hpp:39
double minAngleDeg
Definition quadquality.hpp:36
Definition quadquality.hpp:42
double aspect
mean(s0,s2) vs mean(s1,s3), >= 1.
Definition quadquality.hpp:47
bool convex
all four cross products share the sign of the total area.
Definition quadquality.hpp:51
double maxAngleDeg
Definition quadquality.hpp:44
double minAngleDeg
Definition quadquality.hpp:43
double rectangularity
1 - max_i |theta_i - 90| / 90.
Definition quadquality.hpp:46
double area
positive finite area, evaluated in local coordinates.
Definition quadquality.hpp:50
double skew
|cos(angle between diagonals)|; zero for perpendicular diagonals (e.g. squares/rhombi),...
Definition quadquality.hpp:48
double scaledJacobian
min_i sin(theta_i), signed (negative = folded).
Definition quadquality.hpp:45
int y
Definition terrainerrorfield.cpp:60
double a
Definition terrainerrorfield.cpp:42
double b
Definition terrainerrorfield.cpp:42
double c
Definition terrainerrorfield.cpp:42
int x
Definition terrainerrorfield.cpp:60