Manifold 3.0
Robust geometry
 
Loading...
Searching...
No Matches
common.h
1// Copyright 2021 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 <limits>
17#include <vector>
18
19#ifdef MANIFOLD_DEBUG
20#include <chrono>
21#endif
22
23#include "linalg.h"
24#include "optional_assert.h"
25
26namespace manifold {
31
35namespace la = linalg;
36using vec2 = la::vec<double, 2>;
37using vec3 = la::vec<double, 3>;
38using vec4 = la::vec<double, 4>;
39using bvec4 = la::vec<bool, 4>;
40using mat2 = la::mat<double, 2, 2>;
41using mat3x2 = la::mat<double, 3, 2>;
42using mat4x2 = la::mat<double, 4, 2>;
43using mat2x3 = la::mat<double, 2, 3>;
44using mat3 = la::mat<double, 3, 3>;
45using mat4x3 = la::mat<double, 4, 3>;
46using mat3x4 = la::mat<double, 3, 4>;
47using mat4 = la::mat<double, 4, 4>;
48using ivec2 = la::vec<int, 2>;
49using ivec3 = la::vec<int, 3>;
50using ivec4 = la::vec<int, 4>;
51using quat = la::vec<double, 4>;
53
59
60constexpr double kPi = 3.14159265358979323846264338327950288;
61constexpr double kTwoPi = 6.28318530717958647692528676655900576;
62constexpr double kHalfPi = 1.57079632679489661923132169163975144;
63
69constexpr double radians(double a) { return a * kPi / 180; }
70
76constexpr double degrees(double a) { return a * 180 / kPi; }
77
85constexpr double smoothstep(double edge0, double edge1, double a) {
86 const double x = la::clamp((a - edge0) / (edge1 - edge0), 0, 1);
87 return x * x * (3 - 2 * x);
88}
89
95inline double sind(double x) {
96 if (!la::isfinite(x)) return sin(x);
97 if (x < 0.0) return -sind(-x);
98 int quo;
99 x = remquo(fabs(x), 90.0, &quo);
100 switch (quo % 4) {
101 case 0:
102 return sin(radians(x));
103 case 1:
104 return cos(radians(x));
105 case 2:
106 return -sin(radians(x));
107 case 3:
108 return -cos(radians(x));
109 }
110 return 0.0;
111}
112
118inline double cosd(double x) { return sind(x + 90.0); }
120
126
132using SimplePolygon = std::vector<vec2>;
133
140using Polygons = std::vector<SimplePolygon>;
141
148 size_t halfedge;
153};
154
158struct Box {
159 vec3 min = vec3(std::numeric_limits<double>::infinity());
160 vec3 max = vec3(-std::numeric_limits<double>::infinity());
161
165 constexpr Box() {}
166
170 constexpr Box(const vec3 p1, const vec3 p2) {
171 min = la::min(p1, p2);
172 max = la::max(p1, p2);
173 }
174
178 constexpr vec3 Size() const { return max - min; }
179
183 constexpr vec3 Center() const { return 0.5 * (max + min); }
184
189 constexpr double Scale() const {
190 vec3 absMax = la::max(la::abs(min), la::abs(max));
191 return la::max(absMax.x, la::max(absMax.y, absMax.z));
192 }
193
197 constexpr bool Contains(const vec3& p) const {
198 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
199 }
200
204 constexpr bool Contains(const Box& box) const {
205 return la::all(la::gequal(box.min, min)) &&
206 la::all(la::gequal(max, box.max));
207 }
208
212 void Union(const vec3 p) {
213 min = la::min(min, p);
214 max = la::max(max, p);
215 }
216
220 constexpr Box Union(const Box& box) const {
221 Box out;
222 out.min = la::min(min, box.min);
223 out.max = la::max(max, box.max);
224 return out;
225 }
226
234 constexpr Box Transform(const mat3x4& transform) const {
235 Box out;
236 vec3 minT = transform * vec4(min, 1.0);
237 vec3 maxT = transform * vec4(max, 1.0);
238 out.min = la::min(minT, maxT);
239 out.max = la::max(minT, maxT);
240 return out;
241 }
242
246 constexpr Box operator+(vec3 shift) const {
247 Box out;
248 out.min = min + shift;
249 out.max = max + shift;
250 return out;
251 }
252
256 Box& operator+=(vec3 shift) {
257 min += shift;
258 max += shift;
259 return *this;
260 }
261
265 constexpr Box operator*(vec3 scale) const {
266 Box out;
267 out.min = min * scale;
268 out.max = max * scale;
269 return out;
270 }
271
275 Box& operator*=(vec3 scale) {
276 min *= scale;
277 max *= scale;
278 return *this;
279 }
280
284 constexpr bool DoesOverlap(const Box& box) const {
285 return min.x <= box.max.x && min.y <= box.max.y && min.z <= box.max.z &&
286 max.x >= box.min.x && max.y >= box.min.y && max.z >= box.min.z;
287 }
288
293 constexpr bool DoesOverlap(vec3 p) const { // projected in z
294 return p.x <= max.x && p.x >= min.x && p.y <= max.y && p.y >= min.y;
295 }
296
300 constexpr bool IsFinite() const {
301 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
302 }
303};
304
308struct Rect {
309 vec2 min = vec2(std::numeric_limits<double>::infinity());
310 vec2 max = vec2(-std::numeric_limits<double>::infinity());
311
315 constexpr Rect() {}
316
320 constexpr Rect(const vec2 a, const vec2 b) {
321 min = la::min(a, b);
322 max = la::max(a, b);
323 }
324
329
333 constexpr vec2 Size() const { return max - min; }
334
338 constexpr double Area() const {
339 auto sz = Size();
340 return sz.x * sz.y;
341 }
342
347 constexpr double Scale() const {
348 vec2 absMax = la::max(la::abs(min), la::abs(max));
349 return la::max(absMax.x, absMax.y);
350 }
351
355 constexpr vec2 Center() const { return 0.5 * (max + min); }
356
360 constexpr bool Contains(const vec2& p) const {
361 return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
362 }
363
367 constexpr bool Contains(const Rect& rect) const {
368 return la::all(la::gequal(rect.min, min)) &&
369 la::all(la::gequal(max, rect.max));
370 }
371
375 constexpr bool DoesOverlap(const Rect& rect) const {
376 return min.x <= rect.max.x && min.y <= rect.max.y && max.x >= rect.min.x &&
377 max.y >= rect.min.y;
378 }
379
383 constexpr bool IsEmpty() const { return max.y <= min.y || max.x <= min.x; };
384
388 constexpr bool IsFinite() const {
389 return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
390 }
391
393
397
401 void Union(const vec2 p) {
402 min = la::min(min, p);
403 max = la::max(max, p);
404 }
405
409 constexpr Rect Union(const Rect& rect) const {
410 Rect out;
411 out.min = la::min(min, rect.min);
412 out.max = la::max(max, rect.max);
413 return out;
414 }
415
419 constexpr Rect operator+(const vec2 shift) const {
420 Rect out;
421 out.min = min + shift;
422 out.max = max + shift;
423 return out;
424 }
425
429 Rect& operator+=(const vec2 shift) {
430 min += shift;
431 max += shift;
432 return *this;
433 }
434
438 constexpr Rect operator*(const vec2 scale) const {
439 Rect out;
440 out.min = min * scale;
441 out.max = max * scale;
442 return out;
443 }
444
448 Rect& operator*=(const vec2 scale) {
449 min *= scale;
450 max *= scale;
451 return *this;
452 }
453
461 constexpr Rect Transform(const mat2x3& m) const {
462 Rect rect;
463 rect.min = m * vec3(min, 1);
464 rect.max = m * vec3(max, 1);
465 return rect;
466 }
467
468};
469
474enum class OpType { Add, Subtract, Intersect };
475
476constexpr int DEFAULT_SEGMENTS = 0;
477constexpr double DEFAULT_ANGLE = 10.0;
478constexpr double DEFAULT_LENGTH = 1.0;
489class Quality {
490 private:
491 inline static int circularSegments_ = DEFAULT_SEGMENTS;
492 inline static double circularAngle_ = DEFAULT_ANGLE;
493 inline static double circularEdgeLength_ = DEFAULT_LENGTH;
494
495 public:
506 static void SetMinCircularAngle(double angle) {
507 if (angle <= 0) return;
508 circularAngle_ = angle;
509 }
510
520 static void SetMinCircularEdgeLength(double length) {
521 if (length <= 0) return;
522 circularEdgeLength_ = length;
523 }
524
534 static void SetCircularSegments(int number) {
535 if (number < 3 && number != 0) return;
536 circularSegments_ = number;
537 }
538
546 static int GetCircularSegments(double radius) {
547 if (circularSegments_ > 0) return circularSegments_;
548 int nSegA = 360.0 / circularAngle_;
549 int nSegL = 2.0 * radius * kPi / circularEdgeLength_;
550 int nSeg = fmin(nSegA, nSegL) + 3;
551 nSeg -= nSeg % 4;
552 return std::max(nSeg, 4);
553 }
554
560 static void ResetToDefaults() {
561 circularSegments_ = DEFAULT_SEGMENTS;
562 circularAngle_ = DEFAULT_ANGLE;
563 circularEdgeLength_ = DEFAULT_LENGTH;
564 }
565};
566
567
572
580 bool intermediateChecks = false;
586 bool processOverlaps = true;
589 bool suppressErrors = false;
592 bool cleanupTriangles = true;
598 int verbose = 0;
599};
600
601
602#ifdef MANIFOLD_DEBUG
603template <class T>
604std::ostream& operator<<(std::ostream& out, const la::vec<T, 1>& v) {
605 return out << '{' << v[0] << '}';
606}
607template <class T>
608std::ostream& operator<<(std::ostream& out, const la::vec<T, 2>& v) {
609 return out << '{' << v[0] << ',' << v[1] << '}';
610}
611template <class T>
612std::ostream& operator<<(std::ostream& out, const la::vec<T, 3>& v) {
613 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}';
614}
615template <class T>
616std::ostream& operator<<(std::ostream& out, const la::vec<T, 4>& v) {
617 return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}';
618}
619
620template <class T, int M>
621std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 1>& m) {
622 return out << '{' << m[0] << '}';
623}
624template <class T, int M>
625std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 2>& m) {
626 return out << '{' << m[0] << ',' << m[1] << '}';
627}
628template <class T, int M>
629std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 3>& m) {
630 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}';
631}
632template <class T, int M>
633std::ostream& operator<<(std::ostream& out, const la::mat<T, M, 4>& m) {
634 return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}';
635}
636
637inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
638 return stream << "min: " << box.min << ", "
639 << "max: " << box.max;
640}
641
642inline std::ostream& operator<<(std::ostream& stream, const Rect& box) {
643 return stream << "min: " << box.min << ", "
644 << "max: " << box.max;
645}
646
647inline std::ostream& operator<<(std::ostream& stream, const Smoothness& s) {
648 return stream << "halfedge: " << s.halfedge << ", "
649 << "smoothness: " << s.smoothness;
650}
651
656template <typename T>
657void Dump(const std::vector<T>& vec) {
658 std::cout << "Vec = " << std::endl;
659 for (size_t i = 0; i < vec.size(); ++i) {
660 std::cout << i << ", " << vec[i] << ", " << std::endl;
661 }
662 std::cout << std::endl;
663}
664
665template <typename T>
666void Diff(const std::vector<T>& a, const std::vector<T>& b) {
667 std::cout << "Diff = " << std::endl;
668 if (a.size() != b.size()) {
669 std::cout << "a and b must have the same length, aborting Diff"
670 << std::endl;
671 return;
672 }
673 for (size_t i = 0; i < a.size(); ++i) {
674 if (a[i] != b[i])
675 std::cout << i << ": " << a[i] << ", " << b[i] << std::endl;
676 }
677 std::cout << std::endl;
678}
679
680struct Timer {
681 std::chrono::high_resolution_clock::time_point start, end;
682
683 void Start() { start = std::chrono::high_resolution_clock::now(); }
684
685 void Stop() { end = std::chrono::high_resolution_clock::now(); }
686
687 float Elapsed() {
688 return std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
689 .count();
690 }
691 void Print(std::string message) {
692 std::cout << "----------- " << std::round(Elapsed()) << " ms for "
693 << message << std::endl;
694 }
695};
696#endif
697} // namespace manifold
These static properties control how circular shapes are quantized by default on construction.
Definition common.h:489
static void ResetToDefaults()
Definition common.h:560
static void SetCircularSegments(int number)
Definition common.h:534
static void SetMinCircularAngle(double angle)
Definition common.h:506
static int GetCircularSegments(double radius)
Definition common.h:546
static void SetMinCircularEdgeLength(double length)
Definition common.h:520
int verbose
Definition common.h:598
bool suppressErrors
Definition common.h:589
bool processOverlaps
Definition common.h:586
bool cleanupTriangles
Definition common.h:592
bool selfIntersectionChecks
Definition common.h:583
bool intermediateChecks
Definition common.h:580
Global parameters that control debugging output. Only has an effect when compiled with the MANIFOLD_D...
Definition common.h:577
constexpr double smoothstep(double edge0, double edge1, double a)
Definition common.h:85
constexpr double degrees(double a)
Definition common.h:76
double cosd(double x)
Definition common.h:118
double sind(double x)
Definition common.h:95
constexpr double radians(double a)
Definition common.h:69
size_t halfedge
The halfedge index = 3 * tri + i, referring to Mesh.triVerts[tri][i].
Definition common.h:148
double smoothness
Definition common.h:152
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:140
OpType
Boolean operation type: Add (Union), Subtract (Difference), and Intersect.
Definition common.h:474
std::vector< vec2 > SimplePolygon
Single polygon contour, wound CCW. First and last point are implicitly connected. Should ensure all i...
Definition common.h:132
Defines which edges to sharpen and how much for the Manifold.Smooth() constructor.
Definition common.h:146
Definition linalg.h:61
Definition linalg.h:56
Axis-aligned 3D box, primarily for bounding.
Definition common.h:158
constexpr Box Transform(const mat3x4 &transform) const
Definition common.h:234
constexpr Box operator+(vec3 shift) const
Definition common.h:246
constexpr bool Contains(const Box &box) const
Definition common.h:204
constexpr vec3 Center() const
Definition common.h:183
constexpr bool DoesOverlap(const Box &box) const
Definition common.h:284
constexpr double Scale() const
Definition common.h:189
constexpr Box Union(const Box &box) const
Definition common.h:220
constexpr bool DoesOverlap(vec3 p) const
Definition common.h:293
void Union(const vec3 p)
Definition common.h:212
Box & operator*=(vec3 scale)
Definition common.h:275
constexpr bool IsFinite() const
Definition common.h:300
constexpr vec3 Size() const
Definition common.h:178
constexpr Box operator*(vec3 scale) const
Definition common.h:265
Box & operator+=(vec3 shift)
Definition common.h:256
constexpr Box(const vec3 p1, const vec3 p2)
Definition common.h:170
constexpr Box()
Definition common.h:165
constexpr bool Contains(const vec3 &p) const
Definition common.h:197
Axis-aligned 2D box, primarily for bounding.
Definition common.h:308
Rect & operator*=(const vec2 scale)
Definition common.h:448
constexpr bool Contains(const Rect &rect) const
Definition common.h:367
constexpr bool Contains(const vec2 &p) const
Definition common.h:360
constexpr bool IsEmpty() const
Definition common.h:383
constexpr Rect(const vec2 a, const vec2 b)
Definition common.h:320
constexpr vec2 Size() const
Definition common.h:333
constexpr double Area() const
Definition common.h:338
constexpr double Scale() const
Definition common.h:347
constexpr vec2 Center() const
Definition common.h:355
constexpr Rect operator*(const vec2 scale) const
Definition common.h:438
constexpr Rect operator+(const vec2 shift) const
Definition common.h:419
constexpr Rect Transform(const mat2x3 &m) const
Definition common.h:461
void Union(const vec2 p)
Definition common.h:401
constexpr Rect()
Definition common.h:315
constexpr bool IsFinite() const
Definition common.h:388
constexpr Rect Union(const Rect &rect) const
Definition common.h:409
constexpr bool DoesOverlap(const Rect &rect) const
Definition common.h:375
Rect & operator+=(const vec2 shift)
Definition common.h:429
Definition common.h:680