feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
650
engine/thirdparty/manifold/include/manifold/common.h
vendored
Normal file
650
engine/thirdparty/manifold/include/manifold/common.h
vendored
Normal file
|
|
@ -0,0 +1,650 @@
|
|||
// Copyright 2021 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#ifdef MANIFOLD_DEBUG
|
||||
#include <chrono>
|
||||
#endif
|
||||
|
||||
#include "manifold/linalg.h"
|
||||
|
||||
namespace manifold {
|
||||
/** @addtogroup Math
|
||||
* @ingroup Core
|
||||
* @brief Simple math operations.
|
||||
* */
|
||||
|
||||
/** @addtogroup LinAlg
|
||||
* @{
|
||||
*/
|
||||
namespace la = linalg;
|
||||
using vec2 = la::vec<double, 2>;
|
||||
using vec3 = la::vec<double, 3>;
|
||||
using vec4 = la::vec<double, 4>;
|
||||
using bvec4 = la::vec<bool, 4>;
|
||||
using mat2 = la::mat<double, 2, 2>;
|
||||
using mat3x2 = la::mat<double, 3, 2>;
|
||||
using mat4x2 = la::mat<double, 4, 2>;
|
||||
using mat2x3 = la::mat<double, 2, 3>;
|
||||
using mat3 = la::mat<double, 3, 3>;
|
||||
using mat4x3 = la::mat<double, 4, 3>;
|
||||
using mat3x4 = la::mat<double, 3, 4>;
|
||||
using mat4 = la::mat<double, 4, 4>;
|
||||
using ivec2 = la::vec<int, 2>;
|
||||
using ivec3 = la::vec<int, 3>;
|
||||
using ivec4 = la::vec<int, 4>;
|
||||
using quat = la::vec<double, 4>;
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup Scalar
|
||||
* @ingroup Math
|
||||
* @brief Simple scalar operations.
|
||||
* @{
|
||||
*/
|
||||
|
||||
constexpr double kPi = 3.14159265358979323846264338327950288;
|
||||
constexpr double kTwoPi = 6.28318530717958647692528676655900576;
|
||||
constexpr double kHalfPi = 1.57079632679489661923132169163975144;
|
||||
|
||||
/**
|
||||
* Convert degrees to radians.
|
||||
*
|
||||
* @param a Angle in degrees.
|
||||
*/
|
||||
constexpr double radians(double a) { return a * kPi / 180; }
|
||||
|
||||
/**
|
||||
* Convert radians to degrees.
|
||||
*
|
||||
* @param a Angle in radians.
|
||||
*/
|
||||
constexpr double degrees(double a) { return a * 180 / kPi; }
|
||||
|
||||
/**
|
||||
* Performs smooth Hermite interpolation between 0 and 1 when edge0 < x < edge1.
|
||||
*
|
||||
* @param edge0 Specifies the value of the lower edge of the Hermite function.
|
||||
* @param edge1 Specifies the value of the upper edge of the Hermite function.
|
||||
* @param a Specifies the source value for interpolation.
|
||||
*/
|
||||
constexpr double smoothstep(double edge0, double edge1, double a) {
|
||||
const double x = la::clamp((a - edge0) / (edge1 - edge0), 0, 1);
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sine function where multiples of 90 degrees come out exact.
|
||||
*
|
||||
* @param x Angle in degrees.
|
||||
*/
|
||||
inline double sind(double x) {
|
||||
if (!la::isfinite(x)) return sin(x);
|
||||
if (x < 0.0) return -sind(-x);
|
||||
int quo;
|
||||
x = remquo(fabs(x), 90.0, &quo);
|
||||
switch (quo % 4) {
|
||||
case 0:
|
||||
return sin(radians(x));
|
||||
case 1:
|
||||
return cos(radians(x));
|
||||
case 2:
|
||||
return -sin(radians(x));
|
||||
case 3:
|
||||
return -cos(radians(x));
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cosine function where multiples of 90 degrees come out exact.
|
||||
*
|
||||
* @param x Angle in degrees.
|
||||
*/
|
||||
inline double cosd(double x) { return sind(x + 90.0); }
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup Structs
|
||||
* @ingroup Core
|
||||
* @brief Miscellaneous data structures for interfacing with this library.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Single polygon contour, wound CCW. First and last point are implicitly
|
||||
* connected. Should ensure all input is
|
||||
* [ε-valid](https://github.com/elalish/manifold/wiki/Manifold-Library#definition-of-%CE%B5-valid).
|
||||
*/
|
||||
using SimplePolygon = std::vector<vec2>;
|
||||
|
||||
/**
|
||||
* @brief Set of polygons with holes. Order of contours is arbitrary. Can
|
||||
* contain any depth of nested holes and any number of separate polygons. Should
|
||||
* ensure all input is
|
||||
* [ε-valid](https://github.com/elalish/manifold/wiki/Manifold-Library#definition-of-%CE%B5-valid).
|
||||
*/
|
||||
using Polygons = std::vector<SimplePolygon>;
|
||||
|
||||
/**
|
||||
* @brief Defines which edges to sharpen and how much for the Manifold.Smooth()
|
||||
* constructor.
|
||||
*/
|
||||
struct Smoothness {
|
||||
/// The halfedge index = 3 * tri + i, referring to Mesh.triVerts[tri][i].
|
||||
size_t halfedge;
|
||||
/// A value between 0 and 1, where 0 is sharp and 1 is the default and the
|
||||
/// curvature is interpolated between these values. The two paired halfedges
|
||||
/// can have different values while maintaining C-1 continuity (except for 0).
|
||||
double smoothness;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Axis-aligned 3D box, primarily for bounding.
|
||||
*/
|
||||
struct Box {
|
||||
vec3 min = vec3(std::numeric_limits<double>::infinity());
|
||||
vec3 max = vec3(-std::numeric_limits<double>::infinity());
|
||||
|
||||
/**
|
||||
* Default constructor is an infinite box that contains all space.
|
||||
*/
|
||||
constexpr Box() {}
|
||||
|
||||
/**
|
||||
* Creates a box that contains the two given points.
|
||||
*/
|
||||
constexpr Box(const vec3 p1, const vec3 p2) {
|
||||
min = la::min(p1, p2);
|
||||
max = la::max(p1, p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the Box.
|
||||
*/
|
||||
constexpr vec3 Size() const { return max - min; }
|
||||
|
||||
/**
|
||||
* Returns the center point of the Box.
|
||||
*/
|
||||
constexpr vec3 Center() const { return 0.5 * (max + min); }
|
||||
|
||||
/**
|
||||
* Returns the absolute-largest coordinate value of any contained
|
||||
* point.
|
||||
*/
|
||||
constexpr double Scale() const {
|
||||
vec3 absMax = la::max(la::abs(min), la::abs(max));
|
||||
return la::max(absMax.x, la::max(absMax.y, absMax.z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this box contain (includes equal) the given point?
|
||||
*/
|
||||
constexpr bool Contains(const vec3& p) const {
|
||||
return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this box contain (includes equal) the given box?
|
||||
*/
|
||||
constexpr bool Contains(const Box& box) const {
|
||||
return la::all(la::gequal(box.min, min)) &&
|
||||
la::all(la::gequal(max, box.max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand this box to include the given point.
|
||||
*/
|
||||
void Union(const vec3 p) {
|
||||
min = la::min(min, p);
|
||||
max = la::max(max, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand this box to include the given box.
|
||||
*/
|
||||
constexpr Box Union(const Box& box) const {
|
||||
Box out;
|
||||
out.min = la::min(min, box.min);
|
||||
out.max = la::max(max, box.max);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the given box by the given axis-aligned affine transform.
|
||||
*
|
||||
* Ensure the transform passed in is axis-aligned (rotations are all
|
||||
* multiples of 90 degrees), or else the resulting bounding box will no longer
|
||||
* bound properly.
|
||||
*/
|
||||
constexpr Box Transform(const mat3x4& transform) const {
|
||||
Box out;
|
||||
vec3 minT = transform * vec4(min, 1.0);
|
||||
vec3 maxT = transform * vec4(max, 1.0);
|
||||
out.min = la::min(minT, maxT);
|
||||
out.max = la::max(minT, maxT);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift this box by the given vector.
|
||||
*/
|
||||
constexpr Box operator+(vec3 shift) const {
|
||||
Box out;
|
||||
out.min = min + shift;
|
||||
out.max = max + shift;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift this box in-place by the given vector.
|
||||
*/
|
||||
Box& operator+=(vec3 shift) {
|
||||
min += shift;
|
||||
max += shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale this box by the given vector.
|
||||
*/
|
||||
constexpr Box operator*(vec3 scale) const {
|
||||
Box out;
|
||||
out.min = min * scale;
|
||||
out.max = max * scale;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale this box in-place by the given vector.
|
||||
*/
|
||||
Box& operator*=(vec3 scale) {
|
||||
min *= scale;
|
||||
max *= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this box overlap the one given (including equality)?
|
||||
*/
|
||||
constexpr bool DoesOverlap(const Box& box) const {
|
||||
return min.x <= box.max.x && min.y <= box.max.y && min.z <= box.max.z &&
|
||||
max.x >= box.min.x && max.y >= box.min.y && max.z >= box.min.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given point project within the XY extent of this box
|
||||
* (including equality)?
|
||||
*/
|
||||
constexpr bool DoesOverlap(vec3 p) const { // projected in z
|
||||
return p.x <= max.x && p.x >= min.x && p.y <= max.y && p.y >= min.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this box have finite bounds?
|
||||
*/
|
||||
constexpr bool IsFinite() const {
|
||||
return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Axis-aligned 2D box, primarily for bounding.
|
||||
*/
|
||||
struct Rect {
|
||||
vec2 min = vec2(std::numeric_limits<double>::infinity());
|
||||
vec2 max = vec2(-std::numeric_limits<double>::infinity());
|
||||
|
||||
/**
|
||||
* Default constructor is an empty rectangle..
|
||||
*/
|
||||
constexpr Rect() {}
|
||||
|
||||
/**
|
||||
* Create a rectangle that contains the two given points.
|
||||
*/
|
||||
constexpr Rect(const vec2 a, const vec2 b) {
|
||||
min = la::min(a, b);
|
||||
max = la::max(a, b);
|
||||
}
|
||||
|
||||
/** @name Information
|
||||
* Details of the rectangle
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* Return the dimensions of the rectangle.
|
||||
*/
|
||||
constexpr vec2 Size() const { return max - min; }
|
||||
|
||||
/**
|
||||
* Return the area of the rectangle.
|
||||
*/
|
||||
constexpr double Area() const {
|
||||
auto sz = Size();
|
||||
return sz.x * sz.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute-largest coordinate value of any contained
|
||||
* point.
|
||||
*/
|
||||
constexpr double Scale() const {
|
||||
vec2 absMax = la::max(la::abs(min), la::abs(max));
|
||||
return la::max(absMax.x, absMax.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the center point of the rectangle.
|
||||
*/
|
||||
constexpr vec2 Center() const { return 0.5 * (max + min); }
|
||||
|
||||
/**
|
||||
* Does this rectangle contain (includes on border) the given point?
|
||||
*/
|
||||
constexpr bool Contains(const vec2& p) const {
|
||||
return la::all(la::gequal(p, min)) && la::all(la::gequal(max, p));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this rectangle contain (includes equal) the given rectangle?
|
||||
*/
|
||||
constexpr bool Contains(const Rect& rect) const {
|
||||
return la::all(la::gequal(rect.min, min)) &&
|
||||
la::all(la::gequal(max, rect.max));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this rectangle overlap the one given (including equality)?
|
||||
*/
|
||||
constexpr bool DoesOverlap(const Rect& rect) const {
|
||||
return min.x <= rect.max.x && min.y <= rect.max.y && max.x >= rect.min.x &&
|
||||
max.y >= rect.min.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the rectangle empty (containing no space)?
|
||||
*/
|
||||
constexpr bool IsEmpty() const { return max.y <= min.y || max.x <= min.x; };
|
||||
|
||||
/**
|
||||
* Does this recangle have finite bounds?
|
||||
*/
|
||||
constexpr bool IsFinite() const {
|
||||
return la::all(la::isfinite(min)) && la::all(la::isfinite(max));
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
/** @name Modification
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* Expand this rectangle (in place) to include the given point.
|
||||
*/
|
||||
void Union(const vec2 p) {
|
||||
min = la::min(min, p);
|
||||
max = la::max(max, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand this rectangle to include the given Rect.
|
||||
*/
|
||||
constexpr Rect Union(const Rect& rect) const {
|
||||
Rect out;
|
||||
out.min = la::min(min, rect.min);
|
||||
out.max = la::max(max, rect.max);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift this rectangle by the given vector.
|
||||
*/
|
||||
constexpr Rect operator+(const vec2 shift) const {
|
||||
Rect out;
|
||||
out.min = min + shift;
|
||||
out.max = max + shift;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift this rectangle in-place by the given vector.
|
||||
*/
|
||||
Rect& operator+=(const vec2 shift) {
|
||||
min += shift;
|
||||
max += shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale this rectangle by the given vector.
|
||||
*/
|
||||
constexpr Rect operator*(const vec2 scale) const {
|
||||
Rect out;
|
||||
out.min = min * scale;
|
||||
out.max = max * scale;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale this rectangle in-place by the given vector.
|
||||
*/
|
||||
Rect& operator*=(const vec2 scale) {
|
||||
min *= scale;
|
||||
max *= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the rectangle by the given axis-aligned affine transform.
|
||||
*
|
||||
* Ensure the transform passed in is axis-aligned (rotations are all
|
||||
* multiples of 90 degrees), or else the resulting rectangle will no longer
|
||||
* bound properly.
|
||||
*/
|
||||
constexpr Rect Transform(const mat2x3& m) const {
|
||||
Rect rect;
|
||||
rect.min = m * vec3(min, 1);
|
||||
rect.max = m * vec3(max, 1);
|
||||
return rect;
|
||||
}
|
||||
///@}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Boolean operation type: Add (Union), Subtract (Difference), and
|
||||
* Intersect.
|
||||
*/
|
||||
enum class OpType { Add, Subtract, Intersect };
|
||||
|
||||
constexpr int DEFAULT_SEGMENTS = 0;
|
||||
constexpr double DEFAULT_ANGLE = 10.0;
|
||||
constexpr double DEFAULT_LENGTH = 1.0;
|
||||
/**
|
||||
* @brief These static properties control how circular shapes are quantized by
|
||||
* default on construction.
|
||||
*
|
||||
* If circularSegments is specified, it takes
|
||||
* precedence. If it is zero, then instead the minimum is used of the segments
|
||||
* calculated based on edge length and angle, rounded up to the nearest
|
||||
* multiple of four. To get numbers not divisible by four, circularSegments
|
||||
* must be specified.
|
||||
*/
|
||||
class Quality {
|
||||
private:
|
||||
inline static int circularSegments_ = DEFAULT_SEGMENTS;
|
||||
inline static double circularAngle_ = DEFAULT_ANGLE;
|
||||
inline static double circularEdgeLength_ = DEFAULT_LENGTH;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Sets an angle constraint the default number of circular segments for the
|
||||
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
||||
* Manifold::Revolve() constructors. The number of segments will be rounded up
|
||||
* to the nearest factor of four.
|
||||
*
|
||||
* @param angle The minimum angle in degrees between consecutive segments. The
|
||||
* angle will increase if the the segments hit the minimum edge length.
|
||||
* Default is 10 degrees.
|
||||
*/
|
||||
static void SetMinCircularAngle(double angle) {
|
||||
if (angle <= 0) return;
|
||||
circularAngle_ = angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a length constraint the default number of circular segments for the
|
||||
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
||||
* Manifold::Revolve() constructors. The number of segments will be rounded up
|
||||
* to the nearest factor of four.
|
||||
*
|
||||
* @param length The minimum length of segments. The length will
|
||||
* increase if the the segments hit the minimum angle. Default is 1.0.
|
||||
*/
|
||||
static void SetMinCircularEdgeLength(double length) {
|
||||
if (length <= 0) return;
|
||||
circularEdgeLength_ = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default number of circular segments for the
|
||||
* CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and
|
||||
* Manifold::Revolve() constructors. Overrides the edge length and angle
|
||||
* constraints and sets the number of segments to exactly this value.
|
||||
*
|
||||
* @param number Number of circular segments. Default is 0, meaning no
|
||||
* constraint is applied.
|
||||
*/
|
||||
static void SetCircularSegments(int number) {
|
||||
if (number < 3 && number != 0) return;
|
||||
circularSegments_ = number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the result of the SetMinCircularAngle(),
|
||||
* SetMinCircularEdgeLength(), and SetCircularSegments() defaults.
|
||||
*
|
||||
* @param radius For a given radius of circle, determine how many default
|
||||
* segments there will be.
|
||||
*/
|
||||
static int GetCircularSegments(double radius) {
|
||||
if (circularSegments_ > 0) return circularSegments_;
|
||||
int nSegA = 360.0 / circularAngle_;
|
||||
int nSegL = 2.0 * radius * kPi / circularEdgeLength_;
|
||||
int nSeg = fmin(nSegA, nSegL) + 3;
|
||||
nSeg -= nSeg % 4;
|
||||
return std::max(nSeg, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the circular construction parameters to their defaults if
|
||||
* SetMinCircularAngle, SetMinCircularEdgeLength, or SetCircularSegments have
|
||||
* been called.
|
||||
*/
|
||||
static void ResetToDefaults() {
|
||||
circularSegments_ = DEFAULT_SEGMENTS;
|
||||
circularAngle_ = DEFAULT_ANGLE;
|
||||
circularEdgeLength_ = DEFAULT_LENGTH;
|
||||
}
|
||||
};
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup Debug
|
||||
* @ingroup Optional
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Global parameters that control debugging output. Only has an
|
||||
* effect when compiled with the MANIFOLD_DEBUG flag.
|
||||
*/
|
||||
struct ExecutionParams {
|
||||
/// Perform extra sanity checks and assertions on the intermediate data
|
||||
/// structures.
|
||||
bool intermediateChecks = false;
|
||||
/// Verbose output primarily of the Boolean, including timing info and vector
|
||||
/// sizes.
|
||||
bool verbose = false;
|
||||
/// If processOverlaps is false, a geometric check will be performed to assert
|
||||
/// all triangles are CCW.
|
||||
bool processOverlaps = true;
|
||||
/// Suppresses printed errors regarding CW triangles. Has no effect if
|
||||
/// processOverlaps is true.
|
||||
bool suppressErrors = false;
|
||||
/// Perform optional but recommended triangle cleanups in SimplifyTopology()
|
||||
bool cleanupTriangles = true;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#ifdef MANIFOLD_DEBUG
|
||||
inline std::ostream& operator<<(std::ostream& stream, const Box& box) {
|
||||
return stream << "min: " << box.min << ", "
|
||||
<< "max: " << box.max;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream, const Rect& box) {
|
||||
return stream << "min: " << box.min << ", "
|
||||
<< "max: " << box.max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the contents of this vector to standard output. Only exists if compiled
|
||||
* with MANIFOLD_DEBUG flag.
|
||||
*/
|
||||
template <typename T>
|
||||
void Dump(const std::vector<T>& vec) {
|
||||
std::cout << "Vec = " << std::endl;
|
||||
for (size_t i = 0; i < vec.size(); ++i) {
|
||||
std::cout << i << ", " << vec[i] << ", " << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Diff(const std::vector<T>& a, const std::vector<T>& b) {
|
||||
std::cout << "Diff = " << std::endl;
|
||||
if (a.size() != b.size()) {
|
||||
std::cout << "a and b must have the same length, aborting Diff"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < a.size(); ++i) {
|
||||
if (a[i] != b[i])
|
||||
std::cout << i << ": " << a[i] << ", " << b[i] << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
struct Timer {
|
||||
std::chrono::high_resolution_clock::time_point start, end;
|
||||
|
||||
void Start() { start = std::chrono::high_resolution_clock::now(); }
|
||||
|
||||
void Stop() { end = std::chrono::high_resolution_clock::now(); }
|
||||
|
||||
float Elapsed() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
|
||||
.count();
|
||||
}
|
||||
void Print(std::string message) {
|
||||
std::cout << "----------- " << std::round(Elapsed()) << " ms for "
|
||||
<< message << std::endl;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
} // namespace manifold
|
||||
2601
engine/thirdparty/manifold/include/manifold/linalg.h
vendored
Normal file
2601
engine/thirdparty/manifold/include/manifold/linalg.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
443
engine/thirdparty/manifold/include/manifold/manifold.h
vendored
Normal file
443
engine/thirdparty/manifold/include/manifold/manifold.h
vendored
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
// Copyright 2021 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#ifdef MANIFOLD_EXPORT
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include "manifold/common.h"
|
||||
#include "manifold/vec_view.h"
|
||||
|
||||
namespace manifold {
|
||||
|
||||
/**
|
||||
* @ingroup Debug
|
||||
*
|
||||
* Allows modification of the assertions checked in MANIFOLD_DEBUG mode.
|
||||
*
|
||||
* @return ExecutionParams&
|
||||
*/
|
||||
ExecutionParams& ManifoldParams();
|
||||
|
||||
class CsgNode;
|
||||
class CsgLeafNode;
|
||||
|
||||
/** @addtogroup Core
|
||||
* @brief The central classes of the library
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Mesh input/output suitable for pushing directly into graphics
|
||||
* libraries.
|
||||
*
|
||||
* This may not be manifold since the verts are duplicated along property
|
||||
* boundaries that do not match. The additional merge vectors store this missing
|
||||
* information, allowing the manifold to be reconstructed. MeshGL is an alias
|
||||
* for the standard single-precision version. Use MeshGL64 to output the full
|
||||
* double precision that Manifold uses internally.
|
||||
*/
|
||||
template <typename Precision, typename I = uint32_t>
|
||||
struct MeshGLP {
|
||||
/// Number of property vertices
|
||||
I NumVert() const { return vertProperties.size() / numProp; };
|
||||
/// Number of triangles
|
||||
I NumTri() const { return triVerts.size() / 3; };
|
||||
/// Number of properties per vertex, always >= 3.
|
||||
I numProp = 3;
|
||||
/// Flat, GL-style interleaved list of all vertex properties: propVal =
|
||||
/// vertProperties[vert * numProp + propIdx]. The first three properties are
|
||||
/// always the position x, y, z.
|
||||
std::vector<Precision> vertProperties;
|
||||
/// The vertex indices of the three triangle corners in CCW (from the outside)
|
||||
/// order, for each triangle.
|
||||
std::vector<I> triVerts;
|
||||
/// Optional: A list of only the vertex indicies that need to be merged to
|
||||
/// reconstruct the manifold.
|
||||
std::vector<I> mergeFromVert;
|
||||
/// Optional: The same length as mergeFromVert, and the corresponding value
|
||||
/// contains the vertex to merge with. It will have an identical position, but
|
||||
/// the other properties may differ.
|
||||
std::vector<I> mergeToVert;
|
||||
/// Optional: Indicates runs of triangles that correspond to a particular
|
||||
/// input mesh instance. The runs encompass all of triVerts and are sorted
|
||||
/// by runOriginalID. Run i begins at triVerts[runIndex[i]] and ends at
|
||||
/// triVerts[runIndex[i+1]]. All runIndex values are divisible by 3. Returned
|
||||
/// runIndex will always be 1 longer than runOriginalID, but same length is
|
||||
/// also allowed as input: triVerts.size() will be automatically appended in
|
||||
/// this case.
|
||||
std::vector<I> runIndex;
|
||||
/// Optional: The OriginalID of the mesh this triangle run came from. This ID
|
||||
/// is ideal for reapplying materials to the output mesh. Multiple runs may
|
||||
/// have the same ID, e.g. representing different copies of the same input
|
||||
/// mesh. If you create an input MeshGL that you want to be able to reference
|
||||
/// as one or more originals, be sure to set unique values from ReserveIDs().
|
||||
std::vector<uint32_t> runOriginalID;
|
||||
/// Optional: For each run, a 3x4 transform is stored representing how the
|
||||
/// corresponding original mesh was transformed to create this triangle run.
|
||||
/// This matrix is stored in column-major order and the length of the overall
|
||||
/// vector is 12 * runOriginalID.size().
|
||||
std::vector<Precision> runTransform;
|
||||
/// Optional: Length NumTri, contains the source face ID this
|
||||
/// triangle comes from. When auto-generated, this ID will be a triangle index
|
||||
/// into the original mesh. This index/ID is purely for external use (e.g.
|
||||
/// recreating polygonal faces) and will not affect Manifold's algorithms.
|
||||
std::vector<I> faceID;
|
||||
/// Optional: The X-Y-Z-W weighted tangent vectors for smooth Refine(). If
|
||||
/// non-empty, must be exactly four times as long as Mesh.triVerts. Indexed
|
||||
/// as 4 * (3 * tri + i) + j, i < 3, j < 4, representing the tangent value
|
||||
/// Mesh.triVerts[tri][i] along the CCW edge. If empty, mesh is faceted.
|
||||
std::vector<Precision> halfedgeTangent;
|
||||
/// Tolerance for mesh simplification. When creating a Manifold, the tolerance
|
||||
/// used will be the maximum of this and a baseline tolerance from the size of
|
||||
/// the bounding box. Any edge shorter than tolerance may be collapsed.
|
||||
/// Tolerance may be enlarged when floating point error accumulates.
|
||||
Precision tolerance = 0;
|
||||
|
||||
MeshGLP() = default;
|
||||
|
||||
/**
|
||||
* Updates the mergeFromVert and mergeToVert vectors in order to create a
|
||||
* manifold solid. If the MeshGL is already manifold, no change will occur and
|
||||
* the function will return false. Otherwise, this will merge verts along open
|
||||
* edges within tolerance (the maximum of the MeshGL tolerance and the
|
||||
* baseline bounding-box tolerance), keeping any from the existing merge
|
||||
* vectors, and return true.
|
||||
*
|
||||
* There is no guarantee the result will be manifold - this is a best-effort
|
||||
* helper function designed primarily to aid in the case where a manifold
|
||||
* multi-material MeshGL was produced, but its merge vectors were lost due to
|
||||
* a round-trip through a file format. Constructing a Manifold from the result
|
||||
* will report an error status if it is not manifold.
|
||||
*/
|
||||
bool Merge();
|
||||
|
||||
/**
|
||||
* Returns the x, y, z position of the ith vertex.
|
||||
*
|
||||
* @param v vertex index.
|
||||
*/
|
||||
la::vec<Precision, 3> GetVertPos(size_t v) const {
|
||||
size_t offset = v * numProp;
|
||||
return la::vec<Precision, 3>(vertProperties[offset],
|
||||
vertProperties[offset + 1],
|
||||
vertProperties[offset + 2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the three vertex indices of the ith triangle.
|
||||
*
|
||||
* @param t triangle index.
|
||||
*/
|
||||
la::vec<I, 3> GetTriVerts(size_t t) const {
|
||||
size_t offset = 3 * t;
|
||||
return la::vec<I, 3>(triVerts[offset], triVerts[offset + 1],
|
||||
triVerts[offset + 2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x, y, z, w tangent of the ith halfedge.
|
||||
*
|
||||
* @param h halfedge index (3 * triangle_index + [0|1|2]).
|
||||
*/
|
||||
la::vec<Precision, 4> GetTangent(size_t h) const {
|
||||
size_t offset = 4 * h;
|
||||
return la::vec<Precision, 4>(
|
||||
halfedgeTangent[offset], halfedgeTangent[offset + 1],
|
||||
halfedgeTangent[offset + 2], halfedgeTangent[offset + 3]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Single-precision - ideal for most uses, especially graphics.
|
||||
*/
|
||||
using MeshGL = MeshGLP<float>;
|
||||
/**
|
||||
* @brief Double-precision, 64-bit indices - best for huge meshes.
|
||||
*/
|
||||
using MeshGL64 = MeshGLP<double, uint64_t>;
|
||||
|
||||
/**
|
||||
* @brief This library's internal representation of an oriented, 2-manifold,
|
||||
* triangle mesh - a simple boundary-representation of a solid object. Use this
|
||||
* class to store and operate on solids, and use MeshGL for input and output.
|
||||
*
|
||||
* In addition to storing geometric data, a Manifold can also store an arbitrary
|
||||
* number of vertex properties. These could be anything, e.g. normals, UV
|
||||
* coordinates, colors, etc, but this library is completely agnostic. All
|
||||
* properties are merely float values indexed by channel number. It is up to the
|
||||
* user to associate channel numbers with meaning.
|
||||
*
|
||||
* Manifold allows vertex properties to be shared for efficient storage, or to
|
||||
* have multiple property verts associated with a single geometric vertex,
|
||||
* allowing sudden property changes, e.g. at Boolean intersections, without
|
||||
* sacrificing manifoldness.
|
||||
*
|
||||
* Manifolds also keep track of their relationships to their inputs, via
|
||||
* OriginalIDs and the faceIDs and transforms accessible through MeshGL. This
|
||||
* allows object-level properties to be re-associated with the output after many
|
||||
* operations, particularly useful for materials. Since separate object's
|
||||
* properties are not mixed, there is no requirement that channels have
|
||||
* consistent meaning between different inputs.
|
||||
*/
|
||||
class Manifold {
|
||||
public:
|
||||
/** @name Basics
|
||||
* Copy / move / assignment
|
||||
*/
|
||||
///@{
|
||||
Manifold();
|
||||
~Manifold();
|
||||
Manifold(const Manifold& other);
|
||||
Manifold& operator=(const Manifold& other);
|
||||
Manifold(Manifold&&) noexcept;
|
||||
Manifold& operator=(Manifold&&) noexcept;
|
||||
///@}
|
||||
|
||||
/** @name Input & Output
|
||||
* Create and retrieve arbitrary manifolds
|
||||
*/
|
||||
///@{
|
||||
Manifold(const MeshGL&);
|
||||
Manifold(const MeshGL64&);
|
||||
MeshGL GetMeshGL(int normalIdx = -1) const;
|
||||
MeshGL64 GetMeshGL64(int normalIdx = -1) const;
|
||||
///@}
|
||||
|
||||
/** @name Constructors
|
||||
* Topological ops, primitives, and SDF
|
||||
*/
|
||||
///@{
|
||||
std::vector<Manifold> Decompose() const;
|
||||
static Manifold Compose(const std::vector<Manifold>&);
|
||||
static Manifold Tetrahedron();
|
||||
static Manifold Cube(vec3 size = vec3(1.0), bool center = false);
|
||||
static Manifold Cylinder(double height, double radiusLow,
|
||||
double radiusHigh = -1.0, int circularSegments = 0,
|
||||
bool center = false);
|
||||
static Manifold Sphere(double radius, int circularSegments = 0);
|
||||
static Manifold LevelSet(std::function<double(vec3)> sdf, Box bounds,
|
||||
double edgeLength, double level = 0,
|
||||
double tolerance = -1, bool canParallel = true);
|
||||
///@}
|
||||
|
||||
/** @name Polygons
|
||||
* 3D to 2D and 2D to 3D
|
||||
*/
|
||||
///@{
|
||||
Polygons Slice(double height = 0) const;
|
||||
Polygons Project() const;
|
||||
static Manifold Extrude(const Polygons& crossSection, double height,
|
||||
int nDivisions = 0, double twistDegrees = 0.0,
|
||||
vec2 scaleTop = vec2(1.0));
|
||||
static Manifold Revolve(const Polygons& crossSection,
|
||||
int circularSegments = 0,
|
||||
double revolveDegrees = 360.0f);
|
||||
///@}
|
||||
|
||||
enum class Error {
|
||||
NoError,
|
||||
NonFiniteVertex,
|
||||
NotManifold,
|
||||
VertexOutOfBounds,
|
||||
PropertiesWrongLength,
|
||||
MissingPositionProperties,
|
||||
MergeVectorsDifferentLengths,
|
||||
MergeIndexOutOfBounds,
|
||||
TransformWrongLength,
|
||||
RunIndexWrongLength,
|
||||
FaceIDWrongLength,
|
||||
InvalidConstruction,
|
||||
};
|
||||
|
||||
/** @name Information
|
||||
* Details of the manifold
|
||||
*/
|
||||
///@{
|
||||
Error Status() const;
|
||||
bool IsEmpty() const;
|
||||
size_t NumVert() const;
|
||||
size_t NumEdge() const;
|
||||
size_t NumTri() const;
|
||||
size_t NumProp() const;
|
||||
size_t NumPropVert() const;
|
||||
Box BoundingBox() const;
|
||||
int Genus() const;
|
||||
double GetTolerance() const;
|
||||
///@}
|
||||
|
||||
/** @name Measurement
|
||||
*/
|
||||
///@{
|
||||
double SurfaceArea() const;
|
||||
double Volume() const;
|
||||
double MinGap(const Manifold& other, double searchLength) const;
|
||||
///@}
|
||||
|
||||
/** @name Mesh ID
|
||||
* Details of the manifold's relation to its input meshes, for the purposes
|
||||
* of reapplying mesh properties.
|
||||
*/
|
||||
///@{
|
||||
int OriginalID() const;
|
||||
Manifold AsOriginal() const;
|
||||
static uint32_t ReserveIDs(uint32_t);
|
||||
///@}
|
||||
|
||||
/** @name Transformations
|
||||
*/
|
||||
///@{
|
||||
Manifold Translate(vec3) const;
|
||||
Manifold Scale(vec3) const;
|
||||
Manifold Rotate(double xDegrees, double yDegrees = 0.0,
|
||||
double zDegrees = 0.0) const;
|
||||
Manifold Mirror(vec3) const;
|
||||
Manifold Transform(const mat3x4&) const;
|
||||
Manifold Warp(std::function<void(vec3&)>) const;
|
||||
Manifold WarpBatch(std::function<void(VecView<vec3>)>) const;
|
||||
Manifold SetTolerance(double) const;
|
||||
///@}
|
||||
|
||||
/** @name Boolean
|
||||
* Combine two manifolds
|
||||
*/
|
||||
///@{
|
||||
Manifold Boolean(const Manifold& second, OpType op) const;
|
||||
static Manifold BatchBoolean(const std::vector<Manifold>& manifolds,
|
||||
OpType op);
|
||||
// Boolean operation shorthand
|
||||
Manifold operator+(const Manifold&) const; // Add (Union)
|
||||
Manifold& operator+=(const Manifold&);
|
||||
Manifold operator-(const Manifold&) const; // Subtract (Difference)
|
||||
Manifold& operator-=(const Manifold&);
|
||||
Manifold operator^(const Manifold&) const; // Intersect
|
||||
Manifold& operator^=(const Manifold&);
|
||||
std::pair<Manifold, Manifold> Split(const Manifold&) const;
|
||||
std::pair<Manifold, Manifold> SplitByPlane(vec3 normal,
|
||||
double originOffset) const;
|
||||
Manifold TrimByPlane(vec3 normal, double originOffset) const;
|
||||
///@}
|
||||
|
||||
/** @name Properties
|
||||
* Create and modify vertex properties.
|
||||
*/
|
||||
///@{
|
||||
Manifold SetProperties(
|
||||
int numProp,
|
||||
std::function<void(double*, vec3, const double*)> propFunc) const;
|
||||
Manifold CalculateCurvature(int gaussianIdx, int meanIdx) const;
|
||||
Manifold CalculateNormals(int normalIdx, double minSharpAngle = 60) const;
|
||||
///@}
|
||||
|
||||
/** @name Smoothing
|
||||
* Smooth meshes by calculating tangent vectors and refining to a higher
|
||||
* triangle count.
|
||||
*/
|
||||
///@{
|
||||
Manifold Refine(int) const;
|
||||
Manifold RefineToLength(double) const;
|
||||
Manifold RefineToTolerance(double) const;
|
||||
Manifold SmoothByNormals(int normalIdx) const;
|
||||
Manifold SmoothOut(double minSharpAngle = 60, double minSmoothness = 0) const;
|
||||
static Manifold Smooth(const MeshGL&,
|
||||
const std::vector<Smoothness>& sharpenedEdges = {});
|
||||
static Manifold Smooth(const MeshGL64&,
|
||||
const std::vector<Smoothness>& sharpenedEdges = {});
|
||||
///@}
|
||||
|
||||
/** @name Convex Hull
|
||||
*/
|
||||
///@{
|
||||
Manifold Hull() const;
|
||||
static Manifold Hull(const std::vector<Manifold>& manifolds);
|
||||
static Manifold Hull(const std::vector<vec3>& pts);
|
||||
///@}
|
||||
|
||||
/** @name Testing Hooks
|
||||
* These are just for internal testing.
|
||||
*/
|
||||
///@{
|
||||
bool MatchesTriNormals() const;
|
||||
size_t NumDegenerateTris() const;
|
||||
size_t NumOverlaps(const Manifold& second) const;
|
||||
double GetEpsilon() const;
|
||||
///@}
|
||||
|
||||
struct Impl;
|
||||
|
||||
#ifdef MANIFOLD_EXPORT
|
||||
static Manifold ImportMeshGL64(std::istream& stream);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Manifold(std::shared_ptr<CsgNode> pNode_);
|
||||
Manifold(std::shared_ptr<Impl> pImpl_);
|
||||
static Manifold Invalid();
|
||||
mutable std::shared_ptr<CsgNode> pNode_;
|
||||
|
||||
CsgLeafNode& GetCsgLeafNode() const;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup Debug
|
||||
* @ingroup Optional
|
||||
* @brief Debugging features
|
||||
*
|
||||
* The features require compiler flags to be enabled. Assertions are enabled
|
||||
* with the MANIFOLD_DEBUG flag and then controlled with ExecutionParams.
|
||||
* @{
|
||||
*/
|
||||
#ifdef MANIFOLD_DEBUG
|
||||
inline std::string ToString(const Manifold::Error& error) {
|
||||
switch (error) {
|
||||
case Manifold::Error::NoError:
|
||||
return "No Error";
|
||||
case Manifold::Error::NonFiniteVertex:
|
||||
return "Non Finite Vertex";
|
||||
case Manifold::Error::NotManifold:
|
||||
return "Not Manifold";
|
||||
case Manifold::Error::VertexOutOfBounds:
|
||||
return "Vertex Out Of Bounds";
|
||||
case Manifold::Error::PropertiesWrongLength:
|
||||
return "Properties Wrong Length";
|
||||
case Manifold::Error::MissingPositionProperties:
|
||||
return "Missing Position Properties";
|
||||
case Manifold::Error::MergeVectorsDifferentLengths:
|
||||
return "Merge Vectors Different Lengths";
|
||||
case Manifold::Error::MergeIndexOutOfBounds:
|
||||
return "Merge Index Out Of Bounds";
|
||||
case Manifold::Error::TransformWrongLength:
|
||||
return "Transform Wrong Length";
|
||||
case Manifold::Error::RunIndexWrongLength:
|
||||
return "Run Index Wrong Length";
|
||||
case Manifold::Error::FaceIDWrongLength:
|
||||
return "Face ID Wrong Length";
|
||||
case Manifold::Error::InvalidConstruction:
|
||||
return "Invalid Construction";
|
||||
default:
|
||||
return "Unknown Error";
|
||||
};
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
const Manifold::Error& error) {
|
||||
return stream << ToString(error);
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
} // namespace manifold
|
||||
66
engine/thirdparty/manifold/include/manifold/optional_assert.h
vendored
Normal file
66
engine/thirdparty/manifold/include/manifold/optional_assert.h
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright 2022 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef MANIFOLD_DEBUG
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
/** @addtogroup Debug
|
||||
* @{
|
||||
*/
|
||||
struct userErr : public virtual std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
struct topologyErr : public virtual std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
struct geometryErr : public virtual std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
using logicErr = std::logic_error;
|
||||
|
||||
template <typename Ex>
|
||||
void AssertFail(const char* file, int line, const char* cond, const char* msg) {
|
||||
std::ostringstream output;
|
||||
output << "Error in file: " << file << " (" << line << "): \'" << cond
|
||||
<< "\' is false: " << msg;
|
||||
throw Ex(output.str());
|
||||
}
|
||||
|
||||
template <typename Ex>
|
||||
void AssertFail(const char* file, int line, const std::string& cond,
|
||||
const std::string& msg) {
|
||||
std::ostringstream output;
|
||||
output << "Error in file: " << file << " (" << line << "): \'" << cond
|
||||
<< "\' is false: " << msg;
|
||||
throw Ex(output.str());
|
||||
}
|
||||
|
||||
// DEBUG_ASSERT is slightly slower due to the function call, but gives more
|
||||
// detailed info.
|
||||
#define DEBUG_ASSERT(condition, EX, msg) \
|
||||
if (!(condition)) AssertFail<EX>(__FILE__, __LINE__, #condition, msg);
|
||||
// ASSERT has almost no overhead, so better to use for frequent calls like
|
||||
// vector bounds checking.
|
||||
#define ASSERT(condition, EX) \
|
||||
if (!(condition)) throw(EX);
|
||||
#else
|
||||
#define DEBUG_ASSERT(condition, EX, msg)
|
||||
#define ASSERT(condition, EX)
|
||||
#endif
|
||||
/** @} */
|
||||
62
engine/thirdparty/manifold/include/manifold/polygon.h
vendored
Normal file
62
engine/thirdparty/manifold/include/manifold/polygon.h
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2021 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include "manifold/common.h"
|
||||
|
||||
namespace manifold {
|
||||
|
||||
/** @addtogroup Structs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Polygon vertex.
|
||||
*/
|
||||
struct PolyVert {
|
||||
/// X-Y position
|
||||
vec2 pos;
|
||||
/// ID or index into another vertex vector
|
||||
int idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Single polygon contour, wound CCW, with indices. First and last point
|
||||
* are implicitly connected. Should ensure all input is
|
||||
* [ε-valid](https://github.com/elalish/manifold/wiki/Manifold-Library#definition-of-%CE%B5-valid).
|
||||
*/
|
||||
using SimplePolygonIdx = std::vector<PolyVert>;
|
||||
|
||||
/**
|
||||
* @brief Set of indexed polygons with holes. Order of contours is arbitrary.
|
||||
* Can contain any depth of nested holes and any number of separate polygons.
|
||||
* Should ensure all input is
|
||||
* [ε-valid](https://github.com/elalish/manifold/wiki/Manifold-Library#definition-of-%CE%B5-valid).
|
||||
*/
|
||||
using PolygonsIdx = std::vector<SimplePolygonIdx>;
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup Triangulation
|
||||
* @ingroup Core
|
||||
* @brief Polygon triangulation
|
||||
* @{
|
||||
*/
|
||||
std::vector<ivec3> TriangulateIdx(const PolygonsIdx &polys,
|
||||
double epsilon = -1);
|
||||
|
||||
std::vector<ivec3> Triangulate(const Polygons &polygons, double epsilon = -1);
|
||||
|
||||
ExecutionParams &PolygonParams();
|
||||
/** @} */
|
||||
} // namespace manifold
|
||||
151
engine/thirdparty/manifold/include/manifold/vec_view.h
vendored
Normal file
151
engine/thirdparty/manifold/include/manifold/vec_view.h
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Copyright 2023 The Manifold Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "manifold/optional_assert.h"
|
||||
|
||||
namespace manifold {
|
||||
|
||||
/**
|
||||
* View for Vec, can perform offset operation.
|
||||
* This will be invalidated when the original vector is dropped or changes
|
||||
* length. Roughly equivalent to std::span<T> from c++20
|
||||
*/
|
||||
template <typename T>
|
||||
class VecView {
|
||||
public:
|
||||
using Iter = T *;
|
||||
using IterC = const T *;
|
||||
|
||||
VecView() : ptr_(nullptr), size_(0) {}
|
||||
|
||||
VecView(T *ptr, size_t size) : ptr_(ptr), size_(size) {}
|
||||
|
||||
VecView(const std::vector<std::remove_cv_t<T>> &v)
|
||||
: ptr_(v.data()), size_(v.size()) {}
|
||||
|
||||
VecView(const VecView &other) {
|
||||
ptr_ = other.ptr_;
|
||||
size_ = other.size_;
|
||||
}
|
||||
|
||||
VecView &operator=(const VecView &other) {
|
||||
ptr_ = other.ptr_;
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// allows conversion to a const VecView
|
||||
operator VecView<const T>() const { return {ptr_, size_}; }
|
||||
|
||||
inline const T &operator[](size_t i) const {
|
||||
ASSERT(i < size_, std::out_of_range("Vec out of range"));
|
||||
return ptr_[i];
|
||||
}
|
||||
|
||||
inline T &operator[](size_t i) {
|
||||
ASSERT(i < size_, std::out_of_range("Vec out of range"));
|
||||
return ptr_[i];
|
||||
}
|
||||
|
||||
IterC cbegin() const { return ptr_; }
|
||||
IterC cend() const { return ptr_ + size_; }
|
||||
|
||||
IterC begin() const { return cbegin(); }
|
||||
IterC end() const { return cend(); }
|
||||
|
||||
Iter begin() { return ptr_; }
|
||||
Iter end() { return ptr_ + size_; }
|
||||
|
||||
const T &front() const {
|
||||
ASSERT(size_ != 0,
|
||||
std::out_of_range("Attempt to take the front of an empty vector"));
|
||||
return ptr_[0];
|
||||
}
|
||||
|
||||
const T &back() const {
|
||||
ASSERT(size_ != 0,
|
||||
std::out_of_range("Attempt to take the back of an empty vector"));
|
||||
return ptr_[size_ - 1];
|
||||
}
|
||||
|
||||
T &front() {
|
||||
ASSERT(size_ != 0,
|
||||
std::out_of_range("Attempt to take the front of an empty vector"));
|
||||
return ptr_[0];
|
||||
}
|
||||
|
||||
T &back() {
|
||||
ASSERT(size_ != 0,
|
||||
std::out_of_range("Attempt to take the back of an empty vector"));
|
||||
return ptr_[size_ - 1];
|
||||
}
|
||||
|
||||
size_t size() const { return size_; }
|
||||
|
||||
bool empty() const { return size_ == 0; }
|
||||
|
||||
VecView<T> view(size_t offset = 0,
|
||||
size_t length = std::numeric_limits<size_t>::max()) {
|
||||
if (length == std::numeric_limits<size_t>::max())
|
||||
length = this->size_ - offset;
|
||||
ASSERT(length >= 0, std::out_of_range("Vec::view out of range"));
|
||||
ASSERT(offset + length <= this->size_ && offset >= 0,
|
||||
std::out_of_range("Vec::view out of range"));
|
||||
return VecView<T>(this->ptr_ + offset, length);
|
||||
}
|
||||
|
||||
VecView<const T> cview(
|
||||
size_t offset = 0,
|
||||
size_t length = std::numeric_limits<size_t>::max()) const {
|
||||
if (length == std::numeric_limits<size_t>::max())
|
||||
length = this->size_ - offset;
|
||||
ASSERT(length >= 0, std::out_of_range("Vec::cview out of range"));
|
||||
ASSERT(offset + length <= this->size_ && offset >= 0,
|
||||
std::out_of_range("Vec::cview out of range"));
|
||||
return VecView<const T>(this->ptr_ + offset, length);
|
||||
}
|
||||
|
||||
VecView<const T> view(
|
||||
size_t offset = 0,
|
||||
size_t length = std::numeric_limits<size_t>::max()) const {
|
||||
return cview(offset, length);
|
||||
}
|
||||
|
||||
T *data() { return this->ptr_; }
|
||||
|
||||
const T *data() const { return this->ptr_; }
|
||||
|
||||
#ifdef MANIFOLD_DEBUG
|
||||
void Dump() const {
|
||||
std::cout << "Vec = " << std::endl;
|
||||
for (size_t i = 0; i < size(); ++i) {
|
||||
std::cout << i << ", " << ptr_[i] << ", " << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
T *ptr_ = nullptr;
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
||||
} // namespace manifold
|
||||
Loading…
Add table
Add a link
Reference in a new issue