void TriContourGenerator::find_boundary_lines(Contour& contour, const double& level) { // Traverse boundaries to find starting points for all contour lines that // intersect the boundaries. For each starting point found, follow the // line to its end before continuing. const Triangulation& triang = get_triangulation(); const Boundaries& boundaries = get_boundaries(); for (Boundaries::const_iterator it = boundaries.begin(); it != boundaries.end(); ++it) { const Boundary& boundary = *it; bool startAbove, endAbove = false; for (Boundary::const_iterator itb = boundary.begin(); itb != boundary.end(); ++itb) { if (itb == boundary.begin()) startAbove = get_z(triang.get_triangle_point(*itb)) >= level; else startAbove = endAbove; endAbove = get_z(triang.get_triangle_point(itb->tri, (itb->edge+1)%3)) >= level; if (startAbove && !endAbove) { // This boundary edge is the start point for a contour line, // so follow the line. contour.push_back(ContourLine()); ContourLine& contour_line = contour.back(); TriEdge tri_edge = *itb; follow_interior(contour_line, tri_edge, true, level, false); } } } }
void TriContourGenerator::clear_visited_flags(bool include_boundaries) { // Clear _interiorVisited. std::fill(_interior_visited.begin(), _interior_visited.end(), false); if (include_boundaries) { if (_boundaries_visited.empty()) { const Boundaries& boundaries = get_boundaries(); // Initialise _boundaries_visited. _boundaries_visited.reserve(boundaries.size()); for (Boundaries::const_iterator it = boundaries.begin(); it != boundaries.end(); ++it) _boundaries_visited.push_back(BoundaryVisited(it->size())); // Initialise _boundaries_used. _boundaries_used = BoundariesUsed(boundaries.size()); } // Clear _boundaries_visited. for (BoundariesVisited::iterator it = _boundaries_visited.begin(); it != _boundaries_visited.end(); ++it) std::fill(it->begin(), it->end(), false); // Clear _boundaries_used. std::fill(_boundaries_used.begin(), _boundaries_used.end(), false); } }
void Triangulation::get_boundary_edge(const TriEdge& triEdge, int& boundary, int& edge) const { get_boundaries(); // Ensure _tri_edge_to_boundary_map has been created. TriEdgeToBoundaryMap::const_iterator it = _tri_edge_to_boundary_map.find(triEdge); assert(it != _tri_edge_to_boundary_map.end() && "TriEdge is not on a boundary"); boundary = it->second.boundary; edge = it->second.edge; }
void Triangulation::write_boundaries() const { const Boundaries& bs = get_boundaries(); std::cout << "Number of boundaries: " << bs.size() << std::endl; for (Boundaries::const_iterator it = bs.begin(); it != bs.end(); ++it) { const Boundary& b = *it; std::cout << " Boundary of " << b.size() << " points: "; for (Boundary::const_iterator itb = b.begin(); itb != b.end(); ++itb) { std::cout << *itb << ", "; } std::cout << std::endl; } }
bool TriContourGenerator::follow_boundary(ContourLine& contour_line, TriEdge& tri_edge, const double& lower_level, const double& upper_level, bool on_upper) { const Triangulation& triang = get_triangulation(); const Boundaries& boundaries = get_boundaries(); // Have TriEdge to start at, need equivalent boundary edge. int boundary, edge; triang.get_boundary_edge(tri_edge, boundary, edge); _boundaries_used[boundary] = true; bool stop = false; bool first_edge = true; double z_start, z_end = 0; while (!stop) { assert(!_boundaries_visited[boundary][edge] && "Boundary already visited"); _boundaries_visited[boundary][edge] = true; // z values of start and end points of boundary edge. if (first_edge) z_start = get_z(triang.get_triangle_point(tri_edge)); else z_start = z_end; z_end = get_z(triang.get_triangle_point(tri_edge.tri, (tri_edge.edge+1)%3)); if (z_end > z_start) { // z increasing. if (!(!on_upper && first_edge) && z_end >= lower_level && z_start < lower_level) { stop = true; on_upper = false; } else if (z_end >= upper_level && z_start < upper_level) { stop = true; on_upper = true; } } else { // z decreasing. if (!(on_upper && first_edge) && z_start >= upper_level && z_end < upper_level) { stop = true; on_upper = true; } else if (z_start >= lower_level && z_end < lower_level) { stop = true; on_upper = false; } } first_edge = false; if (!stop) { // Move to next boundary edge, adding point to contour line. edge = (edge+1) % (int)boundaries[boundary].size(); tri_edge = boundaries[boundary][edge]; contour_line.push_back(triang.get_point_coords( triang.get_triangle_point(tri_edge))); } } return on_upper; }
void TriContourGenerator::find_boundary_lines_filled(Contour& contour, const double& lower_level, const double& upper_level) { // Traverse boundaries to find starting points for all contour lines that // intersect the boundaries. For each starting point found, follow the // line to its end before continuing. const Triangulation& triang = get_triangulation(); const Boundaries& boundaries = get_boundaries(); for (Boundaries::size_type i = 0; i < boundaries.size(); ++i) { const Boundary& boundary = boundaries[i]; for (Boundary::size_type j = 0; j < boundary.size(); ++j) { if (!_boundaries_visited[i][j]) { // z values of start and end of this boundary edge. double z_start = get_z(triang.get_triangle_point(boundary[j])); double z_end = get_z(triang.get_triangle_point( boundary[j].tri, (boundary[j].edge+1)%3)); // Does this boundary edge's z increase through upper level // and/or decrease through lower level? bool incr_upper = (z_start < upper_level && z_end >= upper_level); bool decr_lower = (z_start >= lower_level && z_end < lower_level); if (decr_lower || incr_upper) { // Start point for contour line, so follow it. contour.push_back(ContourLine()); ContourLine& contour_line = contour.back(); TriEdge start_tri_edge = boundary[j]; TriEdge tri_edge = start_tri_edge; // Traverse interior and boundaries until return to start. bool on_upper = incr_upper; do { follow_interior(contour_line, tri_edge, true, on_upper ? upper_level : lower_level, on_upper); on_upper = follow_boundary(contour_line, tri_edge, lower_level, upper_level, on_upper); } while (tri_edge != start_tri_edge); // Filled contour lines must not have same first and last // points. if (contour_line.size() > 1 && contour_line.front() == contour_line.back()) contour_line.pop_back(); } } } } // Add full boundaries that lie between the lower and upper levels. These // are boundaries that have not been touched by an internal contour line // which are stored in _boundaries_used. for (Boundaries::size_type i = 0; i < boundaries.size(); ++i) { if (!_boundaries_used[i]) { const Boundary& boundary = boundaries[i]; double z = get_z(triang.get_triangle_point(boundary[0])); if (z >= lower_level && z < upper_level) { contour.push_back(ContourLine()); ContourLine& contour_line = contour.back(); for (Boundary::size_type j = 0; j < boundary.size(); ++j) contour_line.push_back(triang.get_point_coords( triang.get_triangle_point(boundary[j]))); } } } }
// Core subdivision iteration loop struct Mesh_Info * iterate(struct rt_bot_internal *bot, struct Mesh_Info *prev_mesh) { std::map<size_t, std::vector<size_t> >::iterator f_it; std::vector<size_t>::iterator l_it; struct Mesh_Info *starting_mesh; if (!prev_mesh) { starting_mesh = new Mesh_Info; mesh_info_init(bot, starting_mesh); } else { starting_mesh = prev_mesh; } struct Mesh_Info *mesh = new Mesh_Info; mesh->iteration_cnt = starting_mesh->iteration_cnt + 1; find_q_pts(starting_mesh); std::set<std::pair<size_t, size_t> > old_edges; std::set<std::pair<size_t, size_t> >::iterator e_it; get_all_edges(starting_mesh, &old_edges); std::set<std::pair<size_t, size_t> > outer_edges; std::set<size_t > outer_pts; std::set<size_t > outer_faces; get_boundaries(starting_mesh, &outer_pts, &outer_edges, &outer_faces); std::cout << "outer pt count: " << outer_pts.size() << "\n"; std::cout << "outer edge count: " << outer_edges.size() << "\n"; std::cout << "outer face count: " << outer_faces.size() << "\n"; // Relax old points here for (size_t pcnt = 0; pcnt < (size_t)starting_mesh->points_p0.Count(); pcnt++) { mesh->points_p0.Append(*starting_mesh->points_p0.At((int)pcnt)); mesh->iteration_of_insert[pcnt] = starting_mesh->iteration_of_insert[pcnt]; } for (f_it = starting_mesh->face_pts.begin(); f_it != starting_mesh->face_pts.end(); f_it++) { mesh->points_p0.Append(starting_mesh->points_q[(int)(*f_it).first]); mesh->iteration_of_insert[mesh->points_p0.Count()-1] = mesh->iteration_cnt; starting_mesh->index_in_next[(*f_it).first] = mesh->points_p0.Count()-1; } // Use the old faces to guide the insertion of the new. size_t face_cnt = 0; for (f_it = starting_mesh->face_pts.begin(); f_it != starting_mesh->face_pts.end(); f_it++) { std::set<std::pair<size_t, size_t> > face_old_edges; size_t q0 = starting_mesh->index_in_next[(*f_it).first]; l_it = (*f_it).second.begin(); face_old_edges.insert(std::make_pair((*l_it), (*(l_it+1)))); face_old_edges.insert(std::make_pair((*(l_it+1)), (*(l_it+2)))); face_old_edges.insert(std::make_pair((*(l_it+2)), (*l_it))); for (e_it = face_old_edges.begin(); e_it != face_old_edges.end(); e_it++) { std::pair<size_t, size_t> edge = mk_edge((*e_it).first, (*e_it).second); if (old_edges.find(edge) != old_edges.end()) { if (outer_edges.find(edge) == outer_edges.end()) { std::set<size_t> curr_faces = starting_mesh->edges_to_faces[edge]; curr_faces.erase((*f_it).first); size_t q1 = starting_mesh->index_in_next[*curr_faces.begin()]; if (outer_faces.find(q0) != outer_faces.end() && outer_faces.find(q1) != outer_faces.end()) { std::cout << "Got two edge faces\n"; } mesh_add_face((*e_it).first, q1, q0, face_cnt, mesh); face_cnt++; mesh_add_face((*e_it).second, q0, q1, face_cnt, mesh); face_cnt++; old_edges.erase(edge); } else { if (mesh->iteration_cnt % 2 == 0) { std::cout << "second iteration: " << q0 << "\n"; } else { mesh_add_face((*e_it).first, (*e_it).second, q0, face_cnt, mesh); face_cnt++; old_edges.erase(edge); } } } } } delete starting_mesh; return mesh; }