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 <limits>
18#include <memory>
19#include <vector>
20
21#if defined(MANIFOLD_DEBUG) || defined(MANIFOLD_TIMING)
22#include <chrono>
23#include <iostream>
24#endif
25
26#include "./math.h"
27#include "linalg.h"
28
29namespace manifold {
34
38namespace la = linalg;
39using vec2 = la::vec<double, 2>;
40using vec3 = la::vec<double, 3>;
41using vec4 = la::vec<double, 4>;
42using bvec4 = la::vec<bool, 4>;
43using mat2 = la::mat<double, 2, 2>;
44using mat3x2 = la::mat<double, 3, 2>;
45using mat4x2 = la::mat<double, 4, 2>;
46using mat2x3 = la::mat<double, 2, 3>;
47using mat3 = la::mat<double, 3, 3>;
48using mat4x3 = la::mat<double, 4, 3>;
49using mat3x4 = la::mat<double, 3, 4>;
50using mat4 = la::mat<double, 4, 4>;
51using ivec2 = la::vec<int, 2>;
52using ivec3 = la::vec<int, 3>;
53using ivec4 = la::vec<int, 4>;
54using quat = la::vec<double, 4>;
56
62
63constexpr double kPi = 3.14159265358979323846264338327950288;
64constexpr double kTwoPi = 6.28318530717958647692528676655900576;
65constexpr double kHalfPi = 1.57079632679489661923132169163975144;
66
72constexpr double radians(double a) { return a * kPi / 180; }
73
79constexpr double degrees(double a) { return a * 180 / kPi; }
80
88constexpr double smoothstep(double edge0, double edge1, double a) {
89 const double x = la::clamp((a - edge0) / (edge1 - edge0), 0, 1);
90 return x * x * (3 - 2 * x);
91}
92
98inline double sind(double x) {
99 if (!la::isfinite(x)) return NAN;
100 if (x < 0.0) return -sind(-x);
101 int quo;
102 x = std::remquo(std::fabs(x), 90.0, &quo);
103 const double xr = radians(x);
104 switch (quo % 4) {
105 case 0:
106 return math::sin(xr);
107 case 1:
108 return math::cos(xr);
109 case 2:
110 return -math::sin(xr);
111 case 3:
112 return -math::cos(xr);
113 }
114 return 0.0;
115}
116
122inline double cosd(double x) { return sind(x + 90.0); }
124
130
136using SimplePolygon = std::vector<vec2>;
137
144using Polygons = std::vector<SimplePolygon>;
145
152 size_t halfedge;
157};
158
162struct RayHit {
164 uint64_t faceID = 0;
168 double distance = 0;
170 vec3 position = vec3(0.0);
172 vec3 normal = vec3(0.0);
173};
174
215class ExecutionContext {
216 public:
217 ExecutionContext();
218 ~ExecutionContext();
219 ExecutionContext(const ExecutionContext&);
220 ExecutionContext(ExecutionContext&&) noexcept;
221 ExecutionContext& operator=(const ExecutionContext&);
222 ExecutionContext& operator=(ExecutionContext&&) noexcept;
223
225 void Cancel();
227 bool Cancelled() const;
230 double Progress() const;
231
234 struct Impl;
235 std::shared_ptr<Impl> impl_;
236};
237
241struct Box {
242 vec3 min = vec3(std::numeric_limits<double>::infinity());
243 vec3 max = vec3(-std::numeric_limits<double>::infinity());
244
248 constexpr Box() {}
249
253 constexpr Box(const vec3 p1, const vec3 p2) {
254 min = la::min(p1, p2);
255 max = la::max(p1, p2);
256 }
257
261 constexpr vec3 Size() const { return max - min; }
262
266 constexpr vec3 Center() const { return 0.5 * (max + min); }
267
272 constexpr double Scale() const {
273 vec3 absMax = la::max(la::abs(min), la::abs(max));
274 return la::max(absMax.x, la::max(absMax.y, absMax.z));
275 }
276
280 constexpr bool Contains(const vec3& p) const {
281 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
282 }
283
287 constexpr bool Contains(const Box& box) const {
288 return la::all(la::gequal(box.min, min)) &&
289 la::all(la::gequal(max, box.max));
290 }
291
295 constexpr bool operator==(const Box& box) const {
296 return la::all(la::equal(box.min, min)) && la::all(la::equal(max, box.max));
297 }
298
302 constexpr bool operator!=(const Box& box) const { return !(*this == box); }
303
307 void Union(const vec3 p) {
308 min = la::min(min, p);
309 max = la::max(max, p);
310 }
311
315 constexpr Box Union(const Box& box) const {
316 Box out;
317 out.min = la::min(min, box.min);
318 out.max = la::max(max, box.max);
319 return out;
320 }
321
329 constexpr Box Transform(const mat3x4& transform) const {
330 Box out;
331 vec3 minT = transform * vec4(min, 1.0);
332 vec3 maxT = transform * vec4(max, 1.0);
333 out.min = la::min(minT, maxT);
334 out.max = la::max(minT, maxT);
335 return out;
336 }
337
341 constexpr Box operator+(vec3 shift) const {
342 Box out;
343 out.min = min + shift;
344 out.max = max + shift;
345 return out;
346 }
347
351 Box& operator+=(vec3 shift) {
352 min += shift;
353 max += shift;
354 return *this;
355 }
356
360 constexpr Box operator*(vec3 scale) const {
361 Box out;
362 out.min = min * scale;
363 out.max = max * scale;
364 return out;
365 }
366
370 Box& operator*=(vec3 scale) {
371 min *= scale;
372 max *= scale;
373 return *this;
374 }
375
379 constexpr bool DoesOverlap(const Box& box) const {
380 return min.x <= box.max.x && min.y <= box.max.y && min.z <= box.max.z &&
381 max.x >= box.min.x && max.y >= box.min.y && max.z >= box.min.z;
382 }
383
388 constexpr bool DoesOverlap(vec3 p) const { // projected in z
389 return p.x <= max.x && p.x >= min.x && p.y <= max.y && p.y >= min.y;
390 }
391
395 constexpr bool IsFinite() const {
396 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
397 }
398};
399
403struct Rect {
404 vec2 min = vec2(std::numeric_limits<double>::infinity());
405 vec2 max = vec2(-std::numeric_limits<double>::infinity());
406
410 constexpr Rect() {}
411
415 constexpr Rect(const vec2 a, const vec2 b) {
416 min = la::min(a, b);
417 max = la::max(a, b);
418 }
419
424
428 constexpr vec2 Size() const { return max - min; }
429
433 constexpr double Area() const {
434 auto sz = Size();
435 return sz.x * sz.y;
436 }
437
442 constexpr double Scale() const {
443 vec2 absMax = la::max(la::abs(min), la::abs(max));
444 return la::max(absMax.x, absMax.y);
445 }
446
450 constexpr vec2 Center() const { return 0.5 * (max + min); }
451
455 constexpr bool Contains(const vec2& p) const {
456 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
457 }
458
462 constexpr bool Contains(const Rect& rect) const {
463 return la::all(la::gequal(rect.min, min)) &&
464 la::all(la::gequal(max, rect.max));
465 }
466
470 constexpr bool DoesOverlap(const Rect& rect) const {
471 return min.x <= rect.max.x && min.y <= rect.max.y && max.x >= rect.min.x &&
472 max.y >= rect.min.y;
473 }
474
478 constexpr bool IsEmpty() const { return max.y <= min.y || max.x <= min.x; }
479
483 constexpr bool IsFinite() const {
484 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
485 }
486
488
492
496 void Union(const vec2 p) {
497 min = la::min(min, p);
498 max = la::max(max, p);
499 }
500
504 constexpr Rect Union(const Rect& rect) const {
505 Rect out;
506 out.min = la::min(min, rect.min);
507 out.max = la::max(max, rect.max);
508 return out;
509 }
510
514 constexpr Rect operator+(const vec2 shift) const {
515 Rect out;
516 out.min = min + shift;
517 out.max = max + shift;
518 return out;
519 }
520
524 Rect& operator+=(const vec2 shift) {
525 min += shift;
526 max += shift;
527 return *this;
528 }
529
533 constexpr Rect operator*(const vec2 scale) const {
534 Rect out;
535 out.min = min * scale;
536 out.max = max * scale;
537 return out;
538 }
539
543 Rect& operator*=(const vec2 scale) {
544 min *= scale;
545 max *= scale;
546 return *this;
547 }
548
556 constexpr Rect Transform(const mat2x3& m) const {
557 Rect rect;
558 rect.min = m * vec3(min, 1);
559 rect.max = m * vec3(max, 1);
560 return rect;
561 }
562
563};
564
569enum class OpType : char { Add, Subtract, Intersect };
570
571constexpr int DEFAULT_SEGMENTS = 0;
572constexpr double DEFAULT_ANGLE = 10.0;
573constexpr double DEFAULT_LENGTH = 1.0;
584class Quality {
585 public:
586 static void SetMinCircularAngle(double angle);
587 static void SetMinCircularEdgeLength(double length);
588 static void SetCircularSegments(int number);
589 static int GetCircularSegments(double radius);
590 static void ResetToDefaults();
591};
592
593
598
606 bool intermediateChecks = false;
612 bool processOverlaps = true;
615 bool suppressErrors = false;
618 bool cleanupTriangles = true;
623 int verbose = 0;
624};
625
626
627#ifdef MANIFOLD_DEBUG
628
629inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
630 return stream << "min: " << box.min << ", " << "max: " << box.max;
631}
632
633inline std::ostream& operator<<(std::ostream& stream, const Rect& box) {
634 return stream << "min: " << box.min << ", " << "max: " << box.max;
635}
636
637inline std::ostream& operator<<(std::ostream& stream, const Smoothness& s) {
638 return stream << "halfedge: " << s.halfedge << ", "
639 << "smoothness: " << s.smoothness;
640}
641
646template <typename T>
647void Dump(const std::vector<T>& vec) {
648 std::cout << "Vec = " << std::endl;
649 for (size_t i = 0; i < vec.size(); ++i) {
650 std::cout << i << ", " << vec[i] << ", " << std::endl;
651 }
652 std::cout << std::endl;
653}
654
655template <typename T>
656void Diff(const std::vector<T>& a, const std::vector<T>& b) {
657 std::cout << "Diff = " << std::endl;
658 if (a.size() != b.size()) {
659 std::cout << "a and b must have the same length, aborting Diff"
660 << std::endl;
661 return;
662 }
663 for (size_t i = 0; i < a.size(); ++i) {
664 if (a[i] != b[i])
665 std::cout << i << ": " << a[i] << ", " << b[i] << std::endl;
666 }
667 std::cout << std::endl;
668}
669
670#endif
671
672#if defined(MANIFOLD_DEBUG) || defined(MANIFOLD_TIMING)
673struct Timer {
674 std::chrono::high_resolution_clock::time_point start, end;
675
676 void Start() { start = std::chrono::high_resolution_clock::now(); }
677
678 void Stop() { end = std::chrono::high_resolution_clock::now(); }
679
680 float Elapsed() {
681 return std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
682 .count();
683 }
684 void Print(std::string message) {
685 std::cout << "----------- " << std::round(Elapsed()) << " ms for "
686 << message << std::endl;
687 }
688};
689#endif
690} // namespace manifold
bool Cancelled() const
Has cancellation been requested?
void Cancel()
Request cancellation. Can be called from any thread. Idempotent.
These static properties control how circular shapes are quantized by default on construction.
Definition common.h:584
static void SetMinCircularAngle(double angle)
Definition manifold.cpp:57
static void ResetToDefaults()
Definition manifold.cpp:111
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:623
bool suppressErrors
Definition common.h:615
bool processOverlaps
Definition common.h:612
bool cleanupTriangles
Definition common.h:618
bool selfIntersectionChecks
Definition common.h:609
bool intermediateChecks
Definition common.h:606
Global parameters that control debugging output. Only has an effect when compiled with the MANIFOLD_D...
Definition common.h:603
constexpr double smoothstep(double edge0, double edge1, double a)
Definition common.h:88
constexpr double degrees(double a)
Definition common.h:79
double cosd(double x)
Definition common.h:122
double sind(double x)
Definition common.h:98
constexpr double radians(double a)
Definition common.h:72
vec3 position
The 3D position of the hit point.
Definition common.h:170
uint64_t faceID
The triangle index that was hit.
Definition common.h:164
double distance
Definition common.h:168
vec3 normal
The geometric face normal at the hit.
Definition common.h:172
size_t halfedge
The halfedge index = 3 * tri + i, referring to Mesh.triVerts[tri][i].
Definition common.h:152
double smoothness
Definition common.h:156
OpType
Boolean operation type: Add (Union), Subtract (Difference), and Intersect.
Definition common.h:569
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:144
std::vector< vec2 > SimplePolygon
Single polygon contour, wound CCW. First and last point are implicitly connected. Should ensure all i...
Definition common.h:136
Result of a ray cast query against a Manifold.
Definition common.h:162
Defines which edges to sharpen and how much for the Manifold.Smooth() constructor.
Definition common.h:150
Definition linalg.h:63
Definition linalg.h:58
Axis-aligned 3D box, primarily for bounding.
Definition common.h:241
constexpr Box Transform(const mat3x4 &transform) const
Definition common.h:329
constexpr Box operator+(vec3 shift) const
Definition common.h:341
constexpr bool Contains(const Box &box) const
Definition common.h:287
constexpr vec3 Center() const
Definition common.h:266
constexpr bool DoesOverlap(const Box &box) const
Definition common.h:379
constexpr double Scale() const
Definition common.h:272
constexpr Box Union(const Box &box) const
Definition common.h:315
constexpr bool DoesOverlap(vec3 p) const
Definition common.h:388
void Union(const vec3 p)
Definition common.h:307
constexpr bool operator==(const Box &box) const
Definition common.h:295
constexpr bool operator!=(const Box &box) const
Definition common.h:302
Box & operator*=(vec3 scale)
Definition common.h:370
constexpr bool IsFinite() const
Definition common.h:395
constexpr vec3 Size() const
Definition common.h:261
constexpr Box operator*(vec3 scale) const
Definition common.h:360
Box & operator+=(vec3 shift)
Definition common.h:351
constexpr Box(const vec3 p1, const vec3 p2)
Definition common.h:253
constexpr Box()
Definition common.h:248
constexpr bool Contains(const vec3 &p) const
Definition common.h:280
Rect & operator*=(const vec2 scale)
Definition common.h:543
constexpr bool Contains(const Rect &rect) const
Definition common.h:462
constexpr bool Contains(const vec2 &p) const
Definition common.h:455
constexpr bool IsEmpty() const
Definition common.h:478
constexpr Rect(const vec2 a, const vec2 b)
Definition common.h:415
constexpr vec2 Size() const
Definition common.h:428
constexpr double Area() const
Definition common.h:433
constexpr double Scale() const
Definition common.h:442
constexpr vec2 Center() const
Definition common.h:450
constexpr Rect operator*(const vec2 scale) const
Definition common.h:533
constexpr Rect operator+(const vec2 shift) const
Definition common.h:514
constexpr Rect Transform(const mat2x3 &m) const
Definition common.h:556
void Union(const vec2 p)
Definition common.h:496
constexpr Rect()
Definition common.h:410
constexpr bool IsFinite() const
Definition common.h:483
constexpr Rect Union(const Rect &rect) const
Definition common.h:504
constexpr bool DoesOverlap(const Rect &rect) const
Definition common.h:470
Rect & operator+=(const vec2 shift)
Definition common.h:524
Definition common.h:673