Manifold 3.0
Robust geometry
Loading...
Searching...
No Matches
common.h
1// Copyright 2026 The Manifold Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16#include <cmath>
17#include <functional>
18#include <limits>
19#include <memory>
20#include <vector>
21
22#if defined(MANIFOLD_DEBUG) || defined(MANIFOLD_TIMING)
23#include <chrono>
24#include <iostream>
25#endif
26
27#include "./math.h"
28#include "linalg.h"
29
30namespace manifold {
31
32// Forward decls for ExecutionContext factory methods (full defs in
33// manifold.h / mesh.h).
34class Manifold;
35template <typename Precision, typename I = uint32_t>
36struct MeshGLP;
37using MeshGL = MeshGLP<float>;
38using MeshGL64 = MeshGLP<double, uint64_t>;
39struct Box; // defined below; needed by ExecutionContext::LevelSet
40
45
49namespace la = linalg;
50using vec2 = la::vec<double, 2>;
51using vec3 = la::vec<double, 3>;
52using vec4 = la::vec<double, 4>;
53using bvec4 = la::vec<bool, 4>;
54using mat2 = la::mat<double, 2, 2>;
55using mat3x2 = la::mat<double, 3, 2>;
56using mat4x2 = la::mat<double, 4, 2>;
57using mat2x3 = la::mat<double, 2, 3>;
58using mat3 = la::mat<double, 3, 3>;
59using mat4x3 = la::mat<double, 4, 3>;
60using mat3x4 = la::mat<double, 3, 4>;
61using mat4 = la::mat<double, 4, 4>;
62using ivec2 = la::vec<int, 2>;
63using ivec3 = la::vec<int, 3>;
64using ivec4 = la::vec<int, 4>;
65using quat = la::vec<double, 4>;
67
73
74constexpr double kPi = 3.14159265358979323846264338327950288;
75constexpr double kTwoPi = 6.28318530717958647692528676655900576;
76constexpr double kHalfPi = 1.57079632679489661923132169163975144;
77
83constexpr double radians(double a) { return a * kPi / 180; }
84
90constexpr double degrees(double a) { return a * 180 / kPi; }
91
99constexpr double smoothstep(double edge0, double edge1, double a) {
100 const double x = la::clamp((a - edge0) / (edge1 - edge0), 0, 1);
101 return x * x * (3 - 2 * x);
102}
103
109inline double sind(double x) {
110 if (!la::isfinite(x)) return NAN;
111 if (x < 0.0) return -sind(-x);
112 int quo;
113 x = std::remquo(std::fabs(x), 90.0, &quo);
114 const double xr = radians(x);
115 switch (quo % 4) {
116 case 0:
117 return math::sin(xr);
118 case 1:
119 return math::cos(xr);
120 case 2:
121 return -math::sin(xr);
122 case 3:
123 return -math::cos(xr);
124 }
125 return 0.0;
126}
127
133inline double cosd(double x) { return sind(x + 90.0); }
135
141
147using SimplePolygon = std::vector<vec2>;
148
155using Polygons = std::vector<SimplePolygon>;
156
163 size_t halfedge;
168};
169
173struct RayHit {
175 uint64_t faceID = 0;
179 double distance = 0;
181 vec3 position = vec3(0.0);
183 vec3 normal = vec3(0.0);
184};
185
244class ExecutionContext {
245 public:
246 ExecutionContext();
247 ~ExecutionContext();
248 ExecutionContext(const ExecutionContext&);
249 ExecutionContext(ExecutionContext&&) noexcept;
250 ExecutionContext& operator=(const ExecutionContext&);
251 ExecutionContext& operator=(ExecutionContext&&) noexcept;
252
254 void Cancel();
256 bool Cancelled() const;
262 double Progress() const;
263
270 Manifold FromMeshGL(const MeshGL& mesh);
271 Manifold FromMeshGL(const MeshGL64& mesh);
272
277 Manifold Smooth(const MeshGL& mesh,
278 const std::vector<Smoothness>& sharpenedEdges = {});
279 Manifold Smooth(const MeshGL64& mesh,
280 const std::vector<Smoothness>& sharpenedEdges = {});
281
285 Manifold LevelSet(std::function<double(vec3)> sdf, Box bounds,
286 double edgeLength, double level = 0, double tolerance = -1,
287 bool canParallel = true);
288
291 struct Impl;
292 std::shared_ptr<Impl> impl_;
293};
294
298struct Box {
299 vec3 min = vec3(std::numeric_limits<double>::infinity());
300 vec3 max = vec3(-std::numeric_limits<double>::infinity());
301
305 constexpr Box() {}
306
310 constexpr Box(const vec3 p1, const vec3 p2) {
311 min = la::min(p1, p2);
312 max = la::max(p1, p2);
313 }
314
318 constexpr vec3 Size() const { return max - min; }
319
323 constexpr vec3 Center() const { return 0.5 * (max + min); }
324
329 constexpr double Scale() const {
330 vec3 absMax = la::max(la::abs(min), la::abs(max));
331 return la::max(absMax.x, la::max(absMax.y, absMax.z));
332 }
333
337 constexpr bool Contains(const vec3& p) const {
338 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
339 }
340
344 constexpr bool Contains(const Box& box) const {
345 return la::all(la::gequal(box.min, min)) &&
346 la::all(la::gequal(max, box.max));
347 }
348
352 constexpr bool operator==(const Box& box) const {
353 return la::all(la::equal(box.min, min)) && la::all(la::equal(max, box.max));
354 }
355
359 constexpr bool operator!=(const Box& box) const { return !(*this == box); }
360
364 void Union(const vec3 p) {
365 min = la::min(min, p);
366 max = la::max(max, p);
367 }
368
372 constexpr Box Union(const Box& box) const {
373 Box out;
374 out.min = la::min(min, box.min);
375 out.max = la::max(max, box.max);
376 return out;
377 }
378
386 constexpr Box Transform(const mat3x4& transform) const {
387 Box out;
388 vec3 minT = transform * vec4(min, 1.0);
389 vec3 maxT = transform * vec4(max, 1.0);
390 out.min = la::min(minT, maxT);
391 out.max = la::max(minT, maxT);
392 return out;
393 }
394
398 constexpr Box operator+(vec3 shift) const {
399 Box out;
400 out.min = min + shift;
401 out.max = max + shift;
402 return out;
403 }
404
408 Box& operator+=(vec3 shift) {
409 min += shift;
410 max += shift;
411 return *this;
412 }
413
417 constexpr Box operator*(vec3 scale) const {
418 Box out;
419 out.min = min * scale;
420 out.max = max * scale;
421 return out;
422 }
423
427 Box& operator*=(vec3 scale) {
428 min *= scale;
429 max *= scale;
430 return *this;
431 }
432
436 constexpr bool DoesOverlap(const Box& box) const {
437 return min.x <= box.max.x && min.y <= box.max.y && min.z <= box.max.z &&
438 max.x >= box.min.x && max.y >= box.min.y && max.z >= box.min.z;
439 }
440
445 constexpr bool DoesOverlap(vec3 p) const { // projected in z
446 return p.x <= max.x && p.x >= min.x && p.y <= max.y && p.y >= min.y;
447 }
448
452 constexpr bool IsFinite() const {
453 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
454 }
455};
456
460struct Rect {
461 vec2 min = vec2(std::numeric_limits<double>::infinity());
462 vec2 max = vec2(-std::numeric_limits<double>::infinity());
463
467 constexpr Rect() {}
468
472 constexpr Rect(const vec2 a, const vec2 b) {
473 min = la::min(a, b);
474 max = la::max(a, b);
475 }
476
481
485 constexpr vec2 Size() const { return max - min; }
486
490 constexpr double Area() const {
491 auto sz = Size();
492 return sz.x * sz.y;
493 }
494
499 constexpr double Scale() const {
500 vec2 absMax = la::max(la::abs(min), la::abs(max));
501 return la::max(absMax.x, absMax.y);
502 }
503
507 constexpr vec2 Center() const { return 0.5 * (max + min); }
508
512 constexpr bool Contains(const vec2& p) const {
513 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
514 }
515
519 constexpr bool Contains(const Rect& rect) const {
520 return la::all(la::gequal(rect.min, min)) &&
521 la::all(la::gequal(max, rect.max));
522 }
523
527 constexpr bool DoesOverlap(const Rect& rect) const {
528 return min.x <= rect.max.x && min.y <= rect.max.y && max.x >= rect.min.x &&
529 max.y >= rect.min.y;
530 }
531
535 constexpr bool IsEmpty() const { return max.y <= min.y || max.x <= min.x; }
536
540 constexpr bool IsFinite() const {
541 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
542 }
543
545
549
553 void Union(const vec2 p) {
554 min = la::min(min, p);
555 max = la::max(max, p);
556 }
557
561 constexpr Rect Union(const Rect& rect) const {
562 Rect out;
563 out.min = la::min(min, rect.min);
564 out.max = la::max(max, rect.max);
565 return out;
566 }
567
571 constexpr Rect operator+(const vec2 shift) const {
572 Rect out;
573 out.min = min + shift;
574 out.max = max + shift;
575 return out;
576 }
577
581 Rect& operator+=(const vec2 shift) {
582 min += shift;
583 max += shift;
584 return *this;
585 }
586
590 constexpr Rect operator*(const vec2 scale) const {
591 Rect out;
592 out.min = min * scale;
593 out.max = max * scale;
594 return out;
595 }
596
600 Rect& operator*=(const vec2 scale) {
601 min *= scale;
602 max *= scale;
603 return *this;
604 }
605
613 constexpr Rect Transform(const mat2x3& m) const {
614 Rect rect;
615 rect.min = m * vec3(min, 1);
616 rect.max = m * vec3(max, 1);
617 return rect;
618 }
619
620};
621
626enum class OpType : char { Add, Subtract, Intersect };
627
628// Adapted from Clipper2 docs:
629// http://www.angusj.com/clipper2/Docs/Units/Clipper/Types/JoinType.htm
630// (Copyright © 2010-2023 Angus Johnson)
660
661constexpr int DEFAULT_SEGMENTS = 0;
662constexpr double DEFAULT_ANGLE = 10.0;
663constexpr double DEFAULT_LENGTH = 1.0;
674class Quality {
675 public:
676 static void SetMinCircularAngle(double angle);
677 static void SetMinCircularEdgeLength(double length);
678 static void SetCircularSegments(int number);
679 static int GetCircularSegments(double radius);
680 static void ResetToDefaults();
681};
682
683
688
696 bool intermediateChecks = false;
702 bool processOverlaps = true;
705 bool suppressErrors = false;
708 bool cleanupTriangles = true;
713 int verbose = 0;
714};
715
716
717#ifdef MANIFOLD_DEBUG
718
719inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
720 return stream << "min: " << box.min << ", " << "max: " << box.max;
721}
722
723inline std::ostream& operator<<(std::ostream& stream, const Rect& box) {
724 return stream << "min: " << box.min << ", " << "max: " << box.max;
725}
726
727inline std::ostream& operator<<(std::ostream& stream, const Smoothness& s) {
728 return stream << "halfedge: " << s.halfedge << ", "
729 << "smoothness: " << s.smoothness;
730}
731
736template <typename T>
737void Dump(const std::vector<T>& vec) {
738 std::cout << "Vec = " << std::endl;
739 for (size_t i = 0; i < vec.size(); ++i) {
740 std::cout << i << ", " << vec[i] << ", " << std::endl;
741 }
742 std::cout << std::endl;
743}
744
745template <typename T>
746void Diff(const std::vector<T>& a, const std::vector<T>& b) {
747 std::cout << "Diff = " << std::endl;
748 if (a.size() != b.size()) {
749 std::cout << "a and b must have the same length, aborting Diff"
750 << std::endl;
751 return;
752 }
753 for (size_t i = 0; i < a.size(); ++i) {
754 if (a[i] != b[i])
755 std::cout << i << ": " << a[i] << ", " << b[i] << std::endl;
756 }
757 std::cout << std::endl;
758}
759
760#endif
761
762#if defined(MANIFOLD_DEBUG) || defined(MANIFOLD_TIMING)
763struct Timer {
764 std::chrono::high_resolution_clock::time_point start, end;
765
766 void Start() { start = std::chrono::high_resolution_clock::now(); }
767
768 void Stop() { end = std::chrono::high_resolution_clock::now(); }
769
770 float Elapsed() {
771 return std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
772 .count();
773 }
774 void Print(std::string message) {
775 std::cout << "----------- " << std::round(Elapsed()) << " ms for "
776 << message << std::endl;
777 }
778};
779#endif
780} // namespace manifold
Manifold LevelSet(std::function< double(vec3)> sdf, Box bounds, double edgeLength, double level=0, double tolerance=-1, bool canParallel=true)
Manifold FromMeshGL(const MeshGL &mesh)
bool Cancelled() const
Has cancellation been requested?
void Cancel()
Request cancellation. Can be called from any thread. Idempotent.
Manifold Smooth(const MeshGL &mesh, const std::vector< Smoothness > &sharpenedEdges={})
This library's internal representation of an oriented, 2-manifold, triangle mesh - a simple boundary-...
Definition manifold.h:67
These static properties control how circular shapes are quantized by default on construction.
Definition common.h:674
static void SetMinCircularAngle(double angle)
Definition manifold.cpp:57
static void ResetToDefaults()
Definition manifold.cpp:113
static void SetCircularSegments(int number)
Definition manifold.cpp:85
static int GetCircularSegments(double radius)
Definition manifold.cpp:97
static void SetMinCircularEdgeLength(double length)
Definition manifold.cpp:71
int verbose
Definition common.h:713
bool suppressErrors
Definition common.h:705
bool processOverlaps
Definition common.h:702
bool cleanupTriangles
Definition common.h:708
bool selfIntersectionChecks
Definition common.h:699
bool intermediateChecks
Definition common.h:696
Global parameters that control debugging output. Only has an effect when compiled with the MANIFOLD_D...
Definition common.h:693
constexpr double smoothstep(double edge0, double edge1, double a)
Definition common.h:99
constexpr double degrees(double a)
Definition common.h:90
double cosd(double x)
Definition common.h:133
double sind(double x)
Definition common.h:109
constexpr double radians(double a)
Definition common.h:83
vec3 position
The 3D position of the hit point.
Definition common.h:181
uint64_t faceID
The triangle index that was hit.
Definition common.h:175
double distance
Definition common.h:179
vec3 normal
The geometric face normal at the hit.
Definition common.h:183
size_t halfedge
The halfedge index = 3 * tri + i, referring to Mesh.triVerts[tri][i].
Definition common.h:163
double smoothness
Definition common.h:167
OpType
Boolean operation type: Add (Union), Subtract (Difference), and Intersect.
Definition common.h:626
std::vector< SimplePolygon > Polygons
Set of polygons with holes. Order of contours is arbitrary. Can contain any depth of nested holes and...
Definition common.h:155
std::vector< vec2 > SimplePolygon
Single polygon contour, wound CCW. First and last point are implicitly connected. Should ensure all i...
Definition common.h:147
JoinType
Definition common.h:637
@ Bevel
Definition common.h:649
@ Round
Definition common.h:641
@ Square
Definition common.h:638
@ Miter
Definition common.h:644
Result of a ray cast query against a Manifold.
Definition common.h:173
Defines which edges to sharpen and how much for the Manifold.Smooth() constructor.
Definition common.h:161
Definition linalg.h:63
Definition linalg.h:58
Axis-aligned 3D box, primarily for bounding.
Definition common.h:298
constexpr Box Transform(const mat3x4 &transform) const
Definition common.h:386
constexpr Box operator+(vec3 shift) const
Definition common.h:398
constexpr bool Contains(const Box &box) const
Definition common.h:344
constexpr vec3 Center() const
Definition common.h:323
constexpr bool DoesOverlap(const Box &box) const
Definition common.h:436
constexpr double Scale() const
Definition common.h:329
constexpr Box Union(const Box &box) const
Definition common.h:372
constexpr bool DoesOverlap(vec3 p) const
Definition common.h:445
void Union(const vec3 p)
Definition common.h:364
constexpr bool operator==(const Box &box) const
Definition common.h:352
constexpr bool operator!=(const Box &box) const
Definition common.h:359
Box & operator*=(vec3 scale)
Definition common.h:427
constexpr bool IsFinite() const
Definition common.h:452
constexpr vec3 Size() const
Definition common.h:318
constexpr Box operator*(vec3 scale) const
Definition common.h:417
Box & operator+=(vec3 shift)
Definition common.h:408
constexpr Box(const vec3 p1, const vec3 p2)
Definition common.h:310
constexpr Box()
Definition common.h:305
constexpr bool Contains(const vec3 &p) const
Definition common.h:337
Mesh input/output suitable for pushing directly into graphics libraries.
Definition mesh.h:102
Rect & operator*=(const vec2 scale)
Definition common.h:600
constexpr bool Contains(const Rect &rect) const
Definition common.h:519
constexpr bool Contains(const vec2 &p) const
Definition common.h:512
constexpr bool IsEmpty() const
Definition common.h:535
constexpr Rect(const vec2 a, const vec2 b)
Definition common.h:472
constexpr vec2 Size() const
Definition common.h:485
constexpr double Area() const
Definition common.h:490
constexpr double Scale() const
Definition common.h:499
constexpr vec2 Center() const
Definition common.h:507
constexpr Rect operator*(const vec2 scale) const
Definition common.h:590
constexpr Rect operator+(const vec2 shift) const
Definition common.h:571
constexpr Rect Transform(const mat2x3 &m) const
Definition common.h:613
void Union(const vec2 p)
Definition common.h:553
constexpr Rect()
Definition common.h:467
constexpr bool IsFinite() const
Definition common.h:540
constexpr Rect Union(const Rect &rect) const
Definition common.h:561
constexpr bool DoesOverlap(const Rect &rect) const
Definition common.h:527
Rect & operator+=(const vec2 shift)
Definition common.h:581
Definition common.h:763