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.
18
#if defined(HAVE_CONFIG_H)
19
# include <carve_config.h>
22
#include <carve/csg.hpp>
23
#include <carve/timing.hpp>
25
#include "csg_detail.hpp"
26
#include "intersect_common.hpp"
28
void carve::csg::CSG::makeEdgeMap(const carve::csg::FaceLoopList &loops,
30
detail::LoopEdges &edge_map) {
31
#if defined(UNORDERED_COLLECTIONS_SUPPORT_RESIZE)
32
edge_map.resize(edge_count);
35
for (carve::csg::FaceLoop *i = loops.head; i; i = i->next) {
36
edge_map.addFaceLoop(i);
41
#include <carve/polyline.hpp>
43
#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
44
void writePLY(const std::string &out_file, const carve::mesh::MeshSet<3> *poly, bool ascii);
45
void writePLY(const std::string &out_file, const carve::line::PolylineSet *lines, bool ascii);
48
void carve::csg::CSG::findSharedEdges(const detail::LoopEdges &edge_map_a,
49
const detail::LoopEdges &edge_map_b,
50
V2Set &shared_edges) {
51
for (detail::LoopEdges::const_iterator
52
i = edge_map_a.begin(), e = edge_map_a.end();
55
detail::LoopEdges::const_iterator j = edge_map_b.find((*i).first);
56
if (j != edge_map_b.end()) {
57
shared_edges.insert((*i).first);
61
#if defined(CARVE_DEBUG)
62
detail::VVSMap edge_graph;
64
for (V2Set::const_iterator i = shared_edges.begin(); i != shared_edges.end(); ++i) {
65
edge_graph[(*i).first].insert((*i).second);
66
edge_graph[(*i).second].insert((*i).first);
69
std::cerr << "*** testing consistency of edge graph" << std::endl;
70
for (detail::VVSMap::const_iterator i = edge_graph.begin(); i != edge_graph.end(); ++i) {
71
if ((*i).second.size() > 2) {
72
std::cerr << "branch at: " << (*i).first << std::endl;
74
if ((*i).second.size() == 1) {
75
std::cerr << "endpoint at: " << (*i).first << std::endl;
76
std::cerr << "coordinate: " << (*i).first->v << std::endl;
81
carve::line::PolylineSet intersection_graph;
82
intersection_graph.vertices.resize(edge_graph.size());
83
std::map<const carve::mesh::MeshSet<3>::vertex_t *, size_t> vmap;
86
for (detail::VVSMap::const_iterator i = edge_graph.begin(); i != edge_graph.end(); ++i) {
87
intersection_graph.vertices[j].v = (*i).first->v;
88
vmap[(*i).first] = j++;
91
while (edge_graph.size()) {
92
detail::VVSMap::iterator prior_i = edge_graph.begin();
93
carve::mesh::MeshSet<3>::vertex_t *prior = (*prior_i).first;
94
std::vector<size_t> connected;
95
connected.push_back(vmap[prior]);
96
while (prior_i != edge_graph.end() && (*prior_i).second.size()) {
97
carve::mesh::MeshSet<3>::vertex_t *next = *(*prior_i).second.begin();
98
detail::VVSMap::iterator next_i = edge_graph.find(next);
99
CARVE_ASSERT(next_i != edge_graph.end());
100
connected.push_back(vmap[next]);
101
(*prior_i).second.erase(next);
102
(*next_i).second.erase(prior);
103
if (!(*prior_i).second.size()) { edge_graph.erase(prior_i); prior_i = edge_graph.end(); }
104
if (!(*next_i).second.size()) { edge_graph.erase(next_i); next_i = edge_graph.end(); }
108
bool closed = connected.front() == connected.back();
109
for (size_t k = 0; k < connected.size(); ++k) {
110
std::cerr << " " << connected[k];
112
std::cerr << std::endl;
113
intersection_graph.addPolyline(closed, connected.begin(), connected.end());
116
#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
117
std::string out("/tmp/intersection.ply");
118
::writePLY(out, &intersection_graph, true);
122
std::cerr << "*** edge graph consistency test done" << std::endl;
128
#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
129
static carve::mesh::MeshSet<3> *groupToPolyhedron(const carve::csg::FaceLoopGroup &grp) {
130
const carve::csg::FaceLoopList &fl = grp.face_loops;
131
std::vector<carve::mesh::MeshSet<3>::face_t *> faces;
132
faces.reserve(fl.size());
133
for (carve::csg::FaceLoop *f = fl.head; f; f = f->next) {
134
faces.push_back(f->orig_face->create(f->vertices.begin(), f->vertices.end(), false));
136
carve::mesh::MeshSet<3> *poly = new carve::mesh::MeshSet<3>(faces);
138
poly->canonicalize();
145
void carve::csg::CSG::groupFaceLoops(carve::mesh::MeshSet<3> *src,
146
carve::csg::FaceLoopList &face_loops,
147
const carve::csg::detail::LoopEdges &loop_edges,
148
const carve::csg::V2Set &no_cross,
149
carve::csg::FLGroupList &out_loops) {
150
// Find all the groups of face loops that are connected by edges
151
// that are not part of no_cross.
152
// this could potentially be done with a disjoint set data-structure.
153
#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
154
static int call_num = 0;
158
static carve::TimingName GROUP_FACE_LOOPS("groupFaceLoops()");
160
carve::TimingBlock block(GROUP_FACE_LOOPS);
163
while (face_loops.size()) {
164
out_loops.push_back(FaceLoopGroup(src));
165
carve::csg::FaceLoopGroup &group = (out_loops.back());
166
carve::csg::FaceLoopList &curr = (group.face_loops);
167
carve::csg::V2Set &perim = (group.perimeter);
169
carve::csg::FaceLoop *expand = face_loops.head;
171
expand->group = &group;
172
face_loops.remove(expand);
176
std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = (expand->vertices);
177
carve::mesh::MeshSet<3>::vertex_t *v1, *v2;
180
for (size_t i = 0; i < loop.size(); ++i) {
183
carve::csg::V2Set::const_iterator nc = no_cross.find(std::make_pair(v1, v2));
184
if (nc == no_cross.end()) {
185
carve::csg::detail::LoopEdges::const_iterator j;
187
j = loop_edges.find(std::make_pair(v1, v2));
188
if (j != loop_edges.end()) {
189
for (std::list<carve::csg::FaceLoop *>::const_iterator
190
k = (*j).second.begin(), ke = (*j).second.end();
192
if ((*k)->group != NULL ||
193
(*k)->orig_face->mesh != expand->orig_face->mesh) continue;
194
face_loops.remove((*k));
196
(*k)->group = &group;
200
j = loop_edges.find(std::make_pair(v2, v1));
201
if (j != loop_edges.end()) {
202
for (std::list<carve::csg::FaceLoop *>::const_iterator
203
k = (*j).second.begin(), ke = (*j).second.end();
205
if ((*k)->group != NULL ||
206
(*k)->orig_face->mesh != expand->orig_face->mesh) continue;
207
face_loops.remove((*k));
209
(*k)->group = &group;
213
perim.insert(std::make_pair(v1, v2));
217
expand = expand->next;
221
#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
223
carve::mesh::MeshSet<3> *poly = groupToPolyhedron(group);
225
sprintf(buf, "/tmp/group-%d-%p.ply", call_num, &curr);
226
std::string out(buf);
227
::writePLY(out, poly, false);