// 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. #include "./impl.h" #include "./parallel.h" namespace { usingnamespacemanifold; // Returns a normalized vector orthogonal to ref, in the plane of ref and in, // unless in and ref are colinear, in which case it falls back to the plane of // ref and altIn. vec3 OrthogonalTo(vec3 in, vec3 altIn, vec3 ref) { … } double Wrap(double radians) { … } // Get the angle between two unit-vectors. double AngleBetween(vec3 a, vec3 b) { … } // Calculate a tangent vector in the form of a weighted cubic Bezier taking as // input the desired tangent direction (length doesn't matter) and the edge // vector to the neighboring vertex. In a symmetric situation where the tangents // at each end are mirror images of each other, this will result in a circular // arc. vec4 CircularTangent(const vec3& tangent, const vec3& edgeVec) { … } struct InterpTri { … }; } // namespace namespace manifold { /** * Get the property normal associated with the startVert of this halfedge, where * normalIdx shows the beginning of where normals are stored in the properties. */ vec3 Manifold::Impl::GetNormal(int halfedge, int normalIdx) const { … } /** * Returns a circular tangent for the requested halfedge, orthogonal to the * given normal vector, and avoiding folding. */ vec4 Manifold::Impl::TangentFromNormal(const vec3& normal, int halfedge) const { … } /** * Returns true if this halfedge should be marked as the interior of a quad, as * defined by its two triangles referring to the same face, and those triangles * having no further face neighbors beyond. */ bool Manifold::Impl::IsInsideQuad(int halfedge) const { … } /** * Returns true if this halfedge is an interior of a quad, as defined by its * halfedge tangent having negative weight. */ bool Manifold::Impl::IsMarkedInsideQuad(int halfedge) const { … } // sharpenedEdges are referenced to the input Mesh, but the triangles have // been sorted in creating the Manifold, so the indices are converted using // meshRelation_. std::vector<Smoothness> Manifold::Impl::UpdateSharpenedEdges( const std::vector<Smoothness>& sharpenedEdges) const { … } // Find faces containing at least 3 triangles - these will not have // interpolated normals - all their vert normals must match their face normal. Vec<bool> Manifold::Impl::FlatFaces() const { … } // Returns a vector of length numVert that has a tri that is part of a // neighboring flat face if there is only one flat face. If there are none it // gets -1, and if there are more than one it gets -2. Vec<int> Manifold::Impl::VertFlatFace(const Vec<bool>& flatFaces) const { … } Vec<int> Manifold::Impl::VertHalfedge() const { … } std::vector<Smoothness> Manifold::Impl::SharpenEdges( double minSharpAngle, double minSmoothness) const { … } /** * Sharpen tangents that intersect an edge to sharpen that edge. The weight is * unchanged, as this has a squared effect on radius of curvature, except * in the case of zero radius, which is marked with weight = 0. */ void Manifold::Impl::SharpenTangent(int halfedge, double smoothness) { … } /** * Instead of calculating the internal shared normals like CalculateNormals * does, this method fills in vertex properties, unshared across edges that * are bent more than minSharpAngle. */ void Manifold::Impl::SetNormals(int normalIdx, double minSharpAngle) { … } /** * Tangents get flattened to create sharp edges by setting their weight to zero. * This is the natural limit of reducing the weight to increase the sharpness * smoothly. This limit gives a decent shape, but it causes the parameterization * to be stretched and compresses it near the edges, which is good for resolving * tight curvature, but bad for property interpolation. This function fixes the * parameter stretch at the limit for sharp edges, since there is no curvature * to resolve. Note this also changes the overall shape - making it more evenly * curved. */ void Manifold::Impl::LinearizeFlatTangents() { … } /** * Redistribute the tangents around each vertex so that the angles between them * have the same ratios as the angles of the triangles between the corresponding * edges. This avoids folding the output shape and gives smoother results. There * must be at least one fixed halfedge on a vertex for that vertex to be * operated on. If there is only one, then that halfedge is not treated as * fixed, but the whole circle is turned to an average orientation. */ void Manifold::Impl::DistributeTangents(const Vec<bool>& fixedHalfedges) { … } /** * Calculates halfedgeTangent_, allowing the manifold to be refined and * smoothed. The tangents form weighted cubic Beziers along each edge. This * function creates circular arcs where possible (minimizing maximum curvature), * constrained to the indicated property normals. Across edges that form * discontinuities in the normals, the tangent vectors are zero-length, allowing * the shape to form a sharp corner with minimal oscillation. */ void Manifold::Impl::CreateTangents(int normalIdx) { … } /** * Calculates halfedgeTangent_, allowing the manifold to be refined and * smoothed. The tangents form weighted cubic Beziers along each edge. This * function creates circular arcs where possible (minimizing maximum curvature), * constrained to the vertex normals. Where sharpenedEdges are specified, the * tangents are shortened that intersect the sharpened edge, concentrating the * curvature there, while the tangents of the sharp edges themselves are aligned * for continuity. */ void Manifold::Impl::CreateTangents(std::vector<Smoothness> sharpenedEdges) { … } void Manifold::Impl::Refine(std::function<int(vec3, vec4, vec4)> edgeDivisions, bool keepInterior) { … } } // namespace manifold