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::find_interior_lines(Contour& contour, const double& level, bool on_upper, bool filled) { const Triangulation& triang = get_triangulation(); int ntri = triang.get_ntri(); for (int tri = 0; tri < ntri; ++tri) { int visited_index = (on_upper ? tri+ntri : tri); if (_interior_visited[visited_index] || triang.is_masked(tri)) continue; // Triangle has already been visited or is masked. _interior_visited[visited_index] = true; // Determine edge via which to leave this triangle. int edge = get_exit_edge(tri, level, on_upper); assert(edge >= -1 && edge < 3 && "Invalid exit edge"); if (edge == -1) continue; // Contour does not pass through this triangle. // Found start of new contour line loop. contour.push_back(ContourLine()); ContourLine& contour_line = contour.back(); TriEdge tri_edge = triang.get_neighbor_edge(tri, edge); follow_interior(contour_line, tri_edge, false, level, on_upper); if (!filled) // Non-filled contour lines must be closed. contour_line.push_back(contour_line.front()); else if (contour_line.size() > 1 && contour_line.front() == contour_line.back()) // Filled contour lines must not have same first and last points. contour_line.pop_back(); } }
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]))); } } } }