Visual Computing Library
Loading...
Searching...
No Matches
intersection.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_ALGORITHMS_MESH_INTERSECTION_H
24#define VCL_ALGORITHMS_MESH_INTERSECTION_H
25
26#include <vclib/algorithms/core/intersection/element.h>
27#include <vclib/mesh/requirements.h>
28
40namespace vcl {
41
79template<
80 EdgeMeshConcept EdgeMesh,
81 FaceMeshConcept MeshType,
82 PlaneConcept PlaneType>
83EdgeMesh intersection(const MeshType& m, const PlaneType& pl)
84{
85 using VertexType = MeshType::VertexType;
86 using FaceType = MeshType::FaceType;
87 using CoordType = VertexType::CoordType;
88
90
91 std::vector<double> qH(m.vertexContainerSize());
92
93 for (const VertexType& v : m.vertices())
94 qH[m.index(v)] = pl.dist(v.coord());
95
96 for (const FaceType& f : m.faces()) {
97 std::vector<CoordType> ptVec;
98 std::vector<CoordType> nmVec;
99 for (uint j = 0; j < f.vertexNumber(); ++j) {
100 if (qH[m.index(f.vertex(j))] == 0) {
101 ptVec.push_back(f.vertex(j)->coord());
102 if constexpr (HasPerVertexNormal<MeshType>) {
103 if (isPerVertexNormalAvailable(m)) {
104 nmVec.push_back(f.vertex(j)->normal());
105 }
106 }
107 }
108 else if (
109 (qH[m.index(f.vertex(j))] * qH[m.index(f.vertexMod(j + 1))]) <
110 0) {
111 const CoordType& p0 = f.vertex(j)->coord();
112 const CoordType& p1 = f.vertexMod(j + 1)->coord();
113
114 float q0 = qH[m.index(f.vertex(j))];
115 float q1 = qH[m.index(f.vertexMod(j + 1))];
116
117 std::pair<CoordType, CoordType> seg(p0, p1);
118 CoordType pp = pl.segmentIntersection(seg);
119 ptVec.push_back(pp);
120 if constexpr (HasPerVertexNormal<MeshType>) {
121 if (isPerVertexNormalAvailable(m)) {
122 using NormalType = VertexType::NormalType;
123 const NormalType& n0 = f.vertex(j)->normal();
124 const NormalType& n1 = f.vertexMod(j + 1)->normal();
125 CoordType nn =
126 (n0 * fabs(q1) + n1 * fabs(q0)) / fabs(q0 - q1);
127 nmVec.push_back(nn);
128 }
129 }
130 }
131 }
132 if (ptVec.size() >= 2) {
133 uint eid = em.addEdge();
134 uint v0 = em.addVertices(2);
135 uint v1 = v0 + 1;
136 em.vertex(v0).coord() = ptVec[0];
137 em.vertex(v1).coord() = ptVec[1];
138 em.edge(eid).setVertex(0, v0);
139 em.edge(eid).setVertex(1, v1);
140 if constexpr (
142 if (isPerVertexNormalAvailable(m) &&
143 isPerVertexNormalAvailable(em)) {
144 em.vertex(v0).normal() = nmVec[0];
145 em.vertex(v1).normal() = nmVec[1];
146 }
147 }
148 }
149 }
150
151 // // Clean-up: Remove duplicate vertex
152 // tri::Clean<EdgeMeshType>::RemoveDuplicateVertex(em);
153
154 // // Clean-up: Sort edges ensuring orientation coherence
155 // for (size_t j = 1; j < em.edge.size(); j++) {
156 // auto& n = em.edge[j - 1].V(1);
157 // for (size_t i = j; i < em.edge.size(); i++) {
158 // auto& ei = em.edge[i];
159 // if (ei.V(1) == n)
160 // std::swap(ei.V(0), ei.V(1));
161 // if (ei.V(0) == n) {
162 // std::swap(em.edge[j], em.edge[i]);
163 // break;
164 // }
165 // }
166 // }
167
168 return em;
169}
170
189template<FaceMeshConcept MeshType, typename SScalar>
191 const MeshType& m,
192 const Sphere<SScalar>& sphere,
193 double tol)
194{
195 using VertexType = MeshType::VertexType;
196 using CoordType = VertexType::CoordType;
197 using ScalarType = CoordType::ScalarType;
198 using FaceType = MeshType::FaceType;
199
200 auto faceSphereIntersectionFilter = [&sphere](const FaceType& f) -> bool {
201 return intersect(f, sphere);
202 };
203
204 MeshType res = perFaceMeshFilter(m, faceSphereIntersectionFilter);
205
206 uint i = 0;
207 while (i < res.faceContainerSize()) {
208 FaceType& f = res.face(i);
209
210 CoordType witness;
211 std::pair<ScalarType, ScalarType> ires(0, 0);
212
213 bool allIn = true;
214 for (const auto* v : f.vertices()) {
215 allIn = allIn && sphere.isInside(v->coord());
216 }
217 if (!allIn && intersect(f, sphere, witness, ires)) {
218 if (faceArea(f) > tol) {
219 uint v0 = res.addVertices(3);
220 uint v1 = v0 + 1;
221 uint v2 = v0 + 2;
222 uint fi = res.addFaces(4);
223
224 FaceType& f = res.face(i);
225
226 res.vertex(v0).importFrom(*f.vertex(0), false);
227 res.vertex(v0).coord() =
228 (f.vertex(0)->coord() + f.vertex(1)->coord()) / 2;
229 res.vertex(v1).importFrom(*f.vertex(1), false);
230 res.vertex(v1).coord() =
231 (f.vertex(1)->coord() + f.vertex(2)->coord()) / 2;
232 res.vertex(v2).importFrom(*f.vertex(2), false);
233 res.vertex(v2).coord() =
234 (f.vertex(2)->coord() + f.vertex(0)->coord()) / 2;
235
236 res.face(fi).importFrom(f, false);
237 res.face(fi).setVertices(
238 f.vertex(0), &res.vertex(v0), &res.vertex(v2));
239
240 ++fi;
241 res.face(fi).importFrom(f, false);
242 res.face(fi).setVertices(
243 f.vertex(1), &res.vertex(v1), &res.vertex(v0));
244
245 ++fi;
246 res.face(fi).importFrom(f, false);
247 res.face(fi).setVertices(
248 &res.vertex(v0), &res.vertex(v1), &res.vertex(v2));
249
250 ++fi;
251 res.face(fi).importFrom(f, false);
252 res.face(fi).setVertices(
253 &res.vertex(v2), &res.vertex(v1), f.vertex(2));
254
255 res.deleteFace(i);
256 }
257 }
258 if (ires.first > 0.0) { // closest point - radius. If >0 is outside
259 res.deleteFace(i);
260 }
261
262 ++i;
263 }
264
265 return res;
266}
267
275template<FaceMeshConcept MeshType, typename SScalar>
276MeshType intersection(const MeshType& m, const Sphere<SScalar>& sphere)
277{
278 double tol = M_PI * sphere.radius() * sphere.radius() / 100000;
279 return intersection(m, sphere, tol);
280}
281
282} // namespace vcl
283
284#endif // VCL_ALGORITHMS_MESH_INTERSECTION_H
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
Concept that checks if a Mesh has the per Vertex Normal component.
Definition per_vertex.h:128
bool intersect(const FaceType &f, const Box< PointType > &box)
Checks if a face intersects a box.
Definition element.h:57
std::optional< typename SegmentType::PointType > intersection(const PlaneType &plane, const SegmentType &segment)
Returns the intersection point between a plane and a segment, if it exists.
Definition misc.h:368
auto faceArea(const FaceType &f)
Computes the area of a face. Works both for triangle and polygonal faces, and it is optimized in case...
Definition geometry.h:101