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 <vector>
19
20#ifdef MANIFOLD_DEBUG
21#include <chrono>
22#endif
23
24#include "./math.h"
25#include "linalg.h"
26
27namespace manifold {
32
36namespace la = linalg;
37using vec2 = la::vec<double, 2>;
38using vec3 = la::vec<double, 3>;
39using vec4 = la::vec<double, 4>;
40using bvec4 = la::vec<bool, 4>;
41using mat2 = la::mat<double, 2, 2>;
42using mat3x2 = la::mat<double, 3, 2>;
43using mat4x2 = la::mat<double, 4, 2>;
44using mat2x3 = la::mat<double, 2, 3>;
45using mat3 = la::mat<double, 3, 3>;
46using mat4x3 = la::mat<double, 4, 3>;
47using mat3x4 = la::mat<double, 3, 4>;
48using mat4 = la::mat<double, 4, 4>;
49using ivec2 = la::vec<int, 2>;
50using ivec3 = la::vec<int, 3>;
51using ivec4 = la::vec<int, 4>;
52using quat = la::vec<double, 4>;
54
60
61constexpr double kPi = 3.14159265358979323846264338327950288;
62constexpr double kTwoPi = 6.28318530717958647692528676655900576;
63constexpr double kHalfPi = 1.57079632679489661923132169163975144;
64
70constexpr double radians(double a) { return a * kPi / 180; }
71
77constexpr double degrees(double a) { return a * 180 / kPi; }
78
86constexpr double smoothstep(double edge0, double edge1, double a) {
87 const double x = la::clamp((a - edge0) / (edge1 - edge0), 0, 1);
88 return x * x * (3 - 2 * x);
89}
90
96inline double sind(double x) {
97 if (!la::isfinite(x)) return NAN;
98 if (x < 0.0) return -sind(-x);
99 int quo;
100 x = std::remquo(std::fabs(x), 90.0, &quo);
101 const double xr = radians(x);
102 switch (quo % 4) {
103 case 0:
104 return math::sin(xr);
105 case 1:
106 return math::cos(xr);
107 case 2:
108 return -math::sin(xr);
109 case 3:
110 return -math::cos(xr);
111 }
112 return 0.0;
113}
114
120inline double cosd(double x) { return sind(x + 90.0); }
122
128
134using SimplePolygon = std::vector<vec2>;
135
142using Polygons = std::vector<SimplePolygon>;
143
150 size_t halfedge;
155};
156
160struct Box {
161 vec3 min = vec3(std::numeric_limits<double>::infinity());
162 vec3 max = vec3(-std::numeric_limits<double>::infinity());
163
167 constexpr Box() {}
168
172 constexpr Box(const vec3 p1, const vec3 p2) {
173 min = la::min(p1, p2);
174 max = la::max(p1, p2);
175 }
176
180 constexpr vec3 Size() const { return max - min; }
181
185 constexpr vec3 Center() const { return 0.5 * (max + min); }
186
191 constexpr double Scale() const {
192 vec3 absMax = la::max(la::abs(min), la::abs(max));
193 return la::max(absMax.x, la::max(absMax.y, absMax.z));
194 }
195
199 constexpr bool Contains(const vec3& p) const {
200 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
201 }
202
206 constexpr bool Contains(const Box& box) const {
207 return la::all(la::gequal(box.min, min)) &&
208 la::all(la::gequal(max, box.max));
209 }
210
214 void Union(const vec3 p) {
215 min = la::min(min, p);
216 max = la::max(max, p);
217 }
218
222 constexpr Box Union(const Box& box) const {
223 Box out;
224 out.min = la::min(min, box.min);
225 out.max = la::max(max, box.max);
226 return out;
227 }
228
236 constexpr Box Transform(const mat3x4& transform) const {
237 Box out;
238 vec3 minT = transform * vec4(min, 1.0);
239 vec3 maxT = transform * vec4(max, 1.0);
240 out.min = la::min(minT, maxT);
241 out.max = la::max(minT, maxT);
242 return out;
243 }
244
248 constexpr Box operator+(vec3 shift) const {
249 Box out;
250 out.min = min + shift;
251 out.max = max + shift;
252 return out;
253 }
254
258 Box& operator+=(vec3 shift) {
259 min += shift;
260 max += shift;
261 return *this;
262 }
263
267 constexpr Box operator*(vec3 scale) const {
268 Box out;
269 out.min = min * scale;
270 out.max = max * scale;
271 return out;
272 }
273
277 Box& operator*=(vec3 scale) {
278 min *= scale;
279 max *= scale;
280 return *this;
281 }
282
286 constexpr bool DoesOverlap(const Box& box) const {
287 return min.x <= box.max.x && min.y <= box.max.y && min.z <= box.max.z &&
288 max.x >= box.min.x && max.y >= box.min.y && max.z >= box.min.z;
289 }
290
295 constexpr bool DoesOverlap(vec3 p) const { // projected in z
296 return p.x <= max.x && p.x >= min.x && p.y <= max.y && p.y >= min.y;
297 }
298
302 constexpr bool IsFinite() const {
303 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
304 }
305};
306
310struct Rect {
311 vec2 min = vec2(std::numeric_limits<double>::infinity());
312 vec2 max = vec2(-std::numeric_limits<double>::infinity());
313
317 constexpr Rect() {}
318
322 constexpr Rect(const vec2 a, const vec2 b) {
323 min = la::min(a, b);
324 max = la::max(a, b);
325 }
326
331
335 constexpr vec2 Size() const { return max - min; }
336
340 constexpr double Area() const {
341 auto sz = Size();
342 return sz.x * sz.y;
343 }
344
349 constexpr double Scale() const {
350 vec2 absMax = la::max(la::abs(min), la::abs(max));
351 return la::max(absMax.x, absMax.y);
352 }
353
357 constexpr vec2 Center() const { return 0.5 * (max + min); }
358
362 constexpr bool Contains(const vec2& p) const {
363 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
364 }
365
369 constexpr bool Contains(const Rect& rect) const {
370 return la::all(la::gequal(rect.min, min)) &&
371 la::all(la::gequal(max, rect.max));
372 }
373
377 constexpr bool DoesOverlap(const Rect& rect) const {
378 return min.x <= rect.max.x && min.y <= rect.max.y && max.x >= rect.min.x &&
379 max.y >= rect.min.y;
380 }
381
385 constexpr bool IsEmpty() const { return max.y <= min.y || max.x <= min.x; }
386
390 constexpr bool IsFinite() const {
391 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
392 }
393
395
399
403 void Union(const vec2 p) {
404 min = la::min(min, p);
405 max = la::max(max, p);
406 }
407
411 constexpr Rect Union(const Rect& rect) const {
412 Rect out;
413 out.min = la::min(min, rect.min);
414 out.max = la::max(max, rect.max);
415 return out;
416 }
417
421 constexpr Rect operator+(const vec2 shift) const {
422 Rect out;
423 out.min = min + shift;
424 out.max = max + shift;
425 return out;
426 }
427
431 Rect& operator+=(const vec2 shift) {
432 min += shift;
433 max += shift;
434 return *this;
435 }
436
440 constexpr Rect operator*(const vec2 scale) const {
441 Rect out;
442 out.min = min * scale;
443 out.max = max * scale;
444 return out;
445 }
446
450 Rect& operator*=(const vec2 scale) {
451 min *= scale;
452 max *= scale;
453 return *this;
454 }
455
463 constexpr Rect Transform(const mat2x3& m) const {
464 Rect rect;
465 rect.min = m * vec3(min, 1);
466 rect.max = m * vec3(max, 1);
467 return rect;
468 }
469
470};
471
476enum class OpType : char { Add, Subtract, Intersect };
477
478constexpr int DEFAULT_SEGMENTS = 0;
479constexpr double DEFAULT_ANGLE = 10.0;
480constexpr double DEFAULT_LENGTH = 1.0;
491class Quality {
492 public:
493 static void SetMinCircularAngle(double angle);
494 static void SetMinCircularEdgeLength(double length);
495 static void SetCircularSegments(int number);
496 static int GetCircularSegments(double radius);
497 static void ResetToDefaults();
498};
499
500
505
513 bool intermediateChecks = false;
519 bool processOverlaps = true;
522 bool suppressErrors = false;
525 bool cleanupTriangles = true;
530 int verbose = 0;
531};
532
533
534#ifdef MANIFOLD_DEBUG
535
536inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
537 return stream << "min: " << box.min << ", " << "max: " << box.max;
538}
539
540inline std::ostream& operator<<(std::ostream& stream, const Rect& box) {
541 return stream << "min: " << box.min << ", " << "max: " << box.max;
542}
543
544inline std::ostream& operator<<(std::ostream& stream, const Smoothness& s) {
545 return stream << "halfedge: " << s.halfedge << ", "
546 << "smoothness: " << s.smoothness;
547}
548
553template <typename T>
554void Dump(const std::vector<T>& vec) {
555 std::cout << "Vec = " << std::endl;
556 for (size_t i = 0; i < vec.size(); ++i) {
557 std::cout << i << ", " << vec[i] << ", " << std::endl;
558 }
559 std::cout << std::endl;
560}
561
562template <typename T>
563void Diff(const std::vector<T>& a, const std::vector<T>& b) {
564 std::cout << "Diff = " << std::endl;
565 if (a.size() != b.size()) {
566 std::cout << "a and b must have the same length, aborting Diff"
567 << std::endl;
568 return;
569 }
570 for (size_t i = 0; i < a.size(); ++i) {
571 if (a[i] != b[i])
572 std::cout << i << ": " << a[i] << ", " << b[i] << std::endl;
573 }
574 std::cout << std::endl;
575}
576
577struct Timer {
578 std::chrono::high_resolution_clock::time_point start, end;
579
580 void Start() { start = std::chrono::high_resolution_clock::now(); }
581
582 void Stop() { end = std::chrono::high_resolution_clock::now(); }
583
584 float Elapsed() {
585 return std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
586 .count();
587 }
588 void Print(std::string message) {
589 std::cout << "----------- " << std::round(Elapsed()) << " ms for "
590 << message << std::endl;
591 }
592};
593#endif
594} // namespace manifold
These static properties control how circular shapes are quantized by default on construction.
Definition common.h:491
static void SetMinCircularAngle(double angle)
Definition manifold.cpp:56
static void ResetToDefaults()
Definition manifold.cpp:110
static void SetCircularSegments(int number)
Definition manifold.cpp:84
static int GetCircularSegments(double radius)
Definition manifold.cpp:96
static void SetMinCircularEdgeLength(double length)
Definition manifold.cpp:70
int verbose
Definition common.h:530
bool suppressErrors
Definition common.h:522
bool processOverlaps
Definition common.h:519
bool cleanupTriangles
Definition common.h:525
bool selfIntersectionChecks
Definition common.h:516
bool intermediateChecks
Definition common.h:513
Global parameters that control debugging output. Only has an effect when compiled with the MANIFOLD_D...
Definition common.h:510
constexpr double smoothstep(double edge0, double edge1, double a)
Definition common.h:86
constexpr double degrees(double a)
Definition common.h:77
double cosd(double x)
Definition common.h:120
double sind(double x)
Definition common.h:96
constexpr double radians(double a)
Definition common.h:70
size_t halfedge
The halfedge index = 3 * tri + i, referring to Mesh.triVerts[tri][i].
Definition common.h:150
double smoothness
Definition common.h:154
OpType
Boolean operation type: Add (Union), Subtract (Difference), and Intersect.
Definition common.h:476
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:142
std::vector< vec2 > SimplePolygon
Single polygon contour, wound CCW. First and last point are implicitly connected. Should ensure all i...
Definition common.h:134
Defines which edges to sharpen and how much for the Manifold.Smooth() constructor.
Definition common.h:148
Definition linalg.h:63
Definition linalg.h:58
Axis-aligned 3D box, primarily for bounding.
Definition common.h:160
constexpr Box Transform(const mat3x4 &transform) const
Definition common.h:236
constexpr Box operator+(vec3 shift) const
Definition common.h:248
constexpr bool Contains(const Box &box) const
Definition common.h:206
constexpr vec3 Center() const
Definition common.h:185
constexpr bool DoesOverlap(const Box &box) const
Definition common.h:286
constexpr double Scale() const
Definition common.h:191
constexpr Box Union(const Box &box) const
Definition common.h:222
constexpr bool DoesOverlap(vec3 p) const
Definition common.h:295
void Union(const vec3 p)
Definition common.h:214
Box & operator*=(vec3 scale)
Definition common.h:277
constexpr bool IsFinite() const
Definition common.h:302
constexpr vec3 Size() const
Definition common.h:180
constexpr Box operator*(vec3 scale) const
Definition common.h:267
Box & operator+=(vec3 shift)
Definition common.h:258
constexpr Box(const vec3 p1, const vec3 p2)
Definition common.h:172
constexpr Box()
Definition common.h:167
constexpr bool Contains(const vec3 &p) const
Definition common.h:199
Rect & operator*=(const vec2 scale)
Definition common.h:450
constexpr bool Contains(const Rect &rect) const
Definition common.h:369
constexpr bool Contains(const vec2 &p) const
Definition common.h:362
constexpr bool IsEmpty() const
Definition common.h:385
constexpr Rect(const vec2 a, const vec2 b)
Definition common.h:322
constexpr vec2 Size() const
Definition common.h:335
constexpr double Area() const
Definition common.h:340
constexpr double Scale() const
Definition common.h:349
constexpr vec2 Center() const
Definition common.h:357
constexpr Rect operator*(const vec2 scale) const
Definition common.h:440
constexpr Rect operator+(const vec2 shift) const
Definition common.h:421
constexpr Rect Transform(const mat2x3 &m) const
Definition common.h:463
void Union(const vec2 p)
Definition common.h:403
constexpr Rect()
Definition common.h:317
constexpr bool IsFinite() const
Definition common.h:390
constexpr Rect Union(const Rect &rect) const
Definition common.h:411
constexpr bool DoesOverlap(const Rect &rect) const
Definition common.h:377
Rect & operator+=(const vec2 shift)
Definition common.h:431
Definition common.h:577