2
// Copyright (C) 2006-2011 Tobias Sargeant (tobias.sargeant@gmail.com).
3
// All rights reserved.
5
// This file is part of the Carve CSG Library (http://carve-csg.com/)
7
// This file may be used under the terms of the GNU General Public
8
// License version 2.0 as published by the Free Software Foundation
9
// and appearing in the file LICENSE.GPL2 included in the packaging of
12
// This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
13
// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
14
// A PARTICULAR PURPOSE.
20
#include <carve/carve.hpp>
21
#include <carve/collection_types.hpp>
22
#include <carve/iobj.hpp>
28
* \class Intersections
29
* \brief Storage for computed intersections between vertices, edges and faces.
32
struct Intersections : public std::unordered_map<IObj, IObjVMapSmall, IObj_hash> {
33
typedef carve::mesh::MeshSet<3>::vertex_t vertex_t;
34
typedef carve::mesh::MeshSet<3>::edge_t edge_t;
35
typedef carve::mesh::MeshSet<3>::face_t face_t;
37
typedef std::unordered_map<IObj, IObjVMapSmall, IObj_hash> super;
43
* \brief Record the position of intersection between a pair of intersection objects.
45
* @param a The first intersecting object.
46
* @param b The second intersecting object.
47
* @param p The point of intersection.
49
void record(IObj a, IObj b, vertex_t *p) {
50
if (a > b) std::swap(a, b);
56
* \brief Test whether vertex \a v intersects face \a f.
58
* @param v The vertex to test.
59
* @param f The face to test.
61
* @return true, if \a v intersects \a f.
63
bool intersectsFace(vertex_t *v, face_t *f) const;
66
* \brief Collect sets of vertices, edges and faces that intersect \a obj
68
* @param[in] obj The intersection object to search for intersections.
69
* @param[out] collect_v A vector of vertices intersecting \a obj.
70
* @param[out] collect_e A vector of edges intersecting \a obj.
71
* @param[out] collect_f A vector of faces intersecting \a obj.
73
void collect(const IObj &obj,
74
std::vector<vertex_t *> *collect_v,
75
std::vector<edge_t *> *collect_e,
76
std::vector<face_t *> *collect_f) const;
80
* \brief Determine whether two intersection objects intersect.
82
* @param a The first intersection object.
83
* @param b The second intersection object.
85
* @return true, if \a a and \a b intersect.
87
bool intersectsExactly(const IObj &a, const IObj &b) {
88
Intersections::const_iterator i = find(a);
89
if (i == end()) return false;
90
return i->second.find(b) != i->second.end();
94
* \brief Determine whether an intersection object intersects a vertex.
96
* @param a The intersection object.
97
* @param v The vertex.
99
* @return true, if \a a and \a v intersect.
101
bool intersects(const IObj &a, vertex_t *v) {
102
Intersections::const_iterator i = find(a);
103
if (i == end()) return false;
104
if (i->second.find(v) != i->second.end()) return true;
109
* \brief Determine whether an intersection object intersects an edge.
111
* @param a The intersection object.
114
* @return true, if \a a and \a e intersect (either on the edge,
115
* or at either endpoint).
117
bool intersects(const IObj &a, edge_t *e) {
118
Intersections::const_iterator i = find(a);
119
if (i == end()) return false;
120
for (super::data_type::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
121
const IObj &obj = j->first;
122
switch (obj.obtype) {
123
case IObj::OBTYPE_VERTEX:
124
if (obj.vertex == e->v1() || obj.vertex == e->v2()) return true;
126
case IObj::OBTYPE_EDGE:
127
if (obj.edge == e) return true;
137
* \brief Determine whether an intersection object intersects a face.
139
* @param a The intersection object.
142
* @return true, if \a a and \a f intersect (either on the face,
143
* or at any associated edge or vertex).
145
bool intersects(const IObj &a, face_t *f) {
146
Intersections::const_iterator i = find(a);
147
if (i == end()) return false;
148
if (i->second.find(f) != i->second.end()) return true;
151
if (i->second.find(e) != i->second.end()) return true;
152
if (i->second.find(e->vert) != i->second.end()) return true;
154
} while (e != f->edge);
159
* \brief Determine whether an edge intersects another edge.
164
* @return true, if \a e and \a f intersect.
166
bool intersects(edge_t *e1, edge_t *e2) {
167
if (intersects(e1->v1(), e2) || intersects(e1->v2(), e2) || intersects(IObj(e1), e2)) return true;
172
* \brief Determine whether an edge intersects a face.
177
* @return true, if \a e and \a f intersect.
179
bool intersects(edge_t *e, face_t *f) {
180
if (intersects(e->v1(), f) || intersects(e->v2(), f) || intersects(IObj(e), f)) return true;
185
* \brief Determine the faces intersected by an edge.
187
* @tparam face_set_t A collection type holding face_t *
188
* @param[in] e The edge.
189
* @param[out] f The resulting set of faces.
191
template<typename face_set_t>
192
void intersectedFaces(edge_t *e, face_set_t &f) const {
193
std::vector<face_t *> intersected_faces;
194
std::vector<edge_t *> intersected_edges;
195
std::vector<vertex_t *> intersected_vertices;
197
collect(e, &intersected_vertices, &intersected_edges, &intersected_faces);
199
for (unsigned i = 0; i < intersected_vertices.size(); ++i) {
200
facesForVertex(intersected_vertices[i], f);
202
for (unsigned i = 0; i < intersected_edges.size(); ++i) {
203
facesForEdge(intersected_edges[i], f);
205
f.insert(intersected_faces.begin(), intersected_faces.end());
209
* \brief Determine the faces intersected by a vertex.
211
* @tparam face_set_t A collection type holding face_t *
212
* @param[in] v The vertex.
213
* @param[out] f The resulting set of faces.
215
template<typename face_set_t>
216
void intersectedFaces(vertex_t *v, face_set_t &f) const {
217
std::vector<face_t *> intersected_faces;
218
std::vector<edge_t *> intersected_edges;
219
std::vector<vertex_t *> intersected_vertices;
221
collect(v, &intersected_vertices, &intersected_edges, &intersected_faces);
223
for (unsigned i = 0; i < intersected_vertices.size(); ++i) {
224
facesForVertex(intersected_vertices[i], f);
226
for (unsigned i = 0; i < intersected_edges.size(); ++i) {
227
facesForEdge(intersected_edges[i], f);
229
f.insert(intersected_faces.begin(), intersected_faces.end());
233
* \brief Collect the set of faces that contain all vertices in \a verts.
235
* @tparam vertex_set_t A collection type holding vertex_t *
236
* @tparam face_set_t A collection type holding face_t *
237
* @param[in] verts A set of vertices.
238
* @param[out] result The resulting set of faces.
240
template<typename vertex_set_t, typename face_set_t>
241
void commonFaces(const vertex_set_t &verts, face_set_t &result) {
243
std::set<face_t *> ifaces, temp, out;
244
typename vertex_set_t::const_iterator i = verts.begin();
245
if (i == verts.end()) return;
246
intersectedFaces((*i), ifaces);
247
while (++i != verts.end()) {
249
intersectedFaces((*i), temp);
252
std::set_intersection(temp.begin(), temp.end(),
253
ifaces.begin(), ifaces.end(),
257
std::copy(ifaces.begin(), ifaces.end(), set_inserter(result));