Cleanup: Slightly simplify delaunay triangulation input gathering

Separate allocation of input arrays and assignment to input class.
The main purpose is to simplify #111061.
This commit is contained in:
Hans Goudey 2023-12-14 12:28:17 -05:00
parent bb2a289a9a
commit 34bf1f6c0c
3 changed files with 69 additions and 63 deletions

View File

@ -1686,7 +1686,7 @@ static void prepare_need_tri(CDT_data &cd, const IMesh &tm, int t)
cd.is_reversed.append(rev);
}
static CDT_data prepare_cdt_input(const IMesh &tm, int t, const Vector<ITT_value> itts)
static CDT_data prepare_cdt_input(const IMesh &tm, int t, const Span<ITT_value> itts)
{
CDT_data ans;
BLI_assert(tm.face(t)->plane_populated());
@ -1718,7 +1718,7 @@ static CDT_data prepare_cdt_input(const IMesh &tm, int t, const Vector<ITT_value
static CDT_data prepare_cdt_input_for_cluster(const IMesh &tm,
const CoplanarClusterInfo &clinfo,
int c,
const Vector<ITT_value> itts)
const Span<ITT_value> itts)
{
CDT_data ans;
BLI_assert(c < clinfo.tot_cluster());
@ -2086,13 +2086,11 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
static Array<Face *> exact_triangulate_poly(Face *f, IMeshArena *arena)
{
int flen = f->size();
CDT_input<mpq_class> cdt_in;
cdt_in.vert = Array<mpq2>(flen);
cdt_in.face = Array<Vector<int>>(1);
cdt_in.face[0].reserve(flen);
for (int i : f->index_range()) {
cdt_in.face[0].append(i);
}
Array<mpq2> in_verts(flen);
Array<Vector<int>> faces;
faces.first().resize(flen);
std::iota(faces.first().begin(), faces.first().end(), 0);
/* Project poly along dominant axis of normal to get 2d coords. */
if (!f->plane_populated()) {
f->populate_plane(false);
@ -2108,7 +2106,7 @@ static Array<Face *> exact_triangulate_poly(Face *f, IMeshArena *arena)
bool rev = rev1 ^ rev2;
for (int i = 0; i < flen; ++i) {
int ii = rev ? flen - i - 1 : i;
mpq2 &p2d = cdt_in.vert[ii];
mpq2 &p2d = in_verts[ii];
int k = 0;
for (int j = 0; j < 3; ++j) {
if (j != axis) {
@ -2116,6 +2114,11 @@ static Array<Face *> exact_triangulate_poly(Face *f, IMeshArena *arena)
}
}
}
CDT_input<mpq_class> cdt_in;
cdt_in.vert = std::move(in_verts);
cdt_in.face = std::move(faces);
CDT_result<mpq_class> cdt_out = delaunay_2d_calc(cdt_in, CDT_INSIDE);
int n_tris = cdt_out.face.size();
Array<Face *> ans(n_tris);

View File

@ -24,38 +24,38 @@
namespace blender::io::obj {
Vector<Vector<int>> fixup_invalid_polygon(Span<float3> vertex_coords,
Span<int> face_vertex_indices)
Vector<Vector<int>> fixup_invalid_polygon(Span<float3> vert_positions, Span<int> face_verts)
{
using namespace blender::meshintersect;
if (face_vertex_indices.size() < 3) {
if (face_verts.size() < 3) {
return {};
}
const float3 normal = bke::mesh::face_normal_calc(vertex_coords, face_vertex_indices);
const float3 normal = bke::mesh::face_normal_calc(vert_positions, face_verts);
float axis_mat[3][3];
axis_dominant_v3_to_m3(axis_mat, normal);
/* Prepare data for CDT. */
CDT_input<double> input;
input.vert.reinitialize(face_vertex_indices.size());
input.face.reinitialize(1);
input.face[0].resize(face_vertex_indices.size());
for (int64_t i = 0; i < face_vertex_indices.size(); ++i) {
input.face[0][i] = i;
}
input.epsilon = 1.0e-6f;
input.need_ids = true;
/* Project vertices to 2D. */
for (size_t i = 0; i < face_vertex_indices.size(); ++i) {
int idx = face_vertex_indices[i];
BLI_assert(idx >= 0 && idx < vertex_coords.size());
float3 coord = vertex_coords[idx];
Array<double2> input_verts(face_verts.size());
for (const int i : face_verts.index_range()) {
int idx = face_verts[i];
BLI_assert(idx >= 0 && idx < vert_positions.size());
float2 coord2d;
mul_v2_m3v3(coord2d, axis_mat, coord);
input.vert[i] = double2(coord2d.x, coord2d.y);
mul_v2_m3v3(coord2d, axis_mat, vert_positions[idx]);
input_verts[i] = double2(coord2d.x, coord2d.y);
}
Array<Vector<int>> input_faces(1);
input_faces.first().resize(input_verts.size());
std::iota(input_faces.first().begin(), input_faces.first().end(), 0);
/* Prepare data for CDT. */
CDT_input<double> input;
input.vert = std::move(input_verts);
input.face = std::move(input_faces);
input.epsilon = 1.0e-6f;
input.need_ids = true;
CDT_result<double> res = delaunay_2d_calc(input, CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES);
/* Emit new face information from CDT result. */
@ -77,7 +77,7 @@ Vector<Vector<int>> fixup_invalid_polygon(Span<float3> vertex_coords,
else {
/* Vertex corresponds to one or more of the input vertices, use it. */
idx = res.vert_orig[idx][0];
BLI_assert(idx >= 0 && idx < face_vertex_indices.size());
BLI_assert(idx >= 0 && idx < face_verts.size());
face_verts.append(idx);
}
}

View File

@ -52,32 +52,39 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = data;
}
static void fill_curve_vert_indices(const OffsetIndices<int> offsets,
MutableSpan<Vector<int>> faces)
{
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
faces[i].resize(offsets[i].size());
array_utils::fill_index_range<int>(faces[i], offsets[i].start());
}
});
}
static meshintersect::CDT_result<double> do_cdt(const bke::CurvesGeometry &curves,
const CDT_output_type output_type)
{
const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
const Span<float3> positions = curves.evaluated_positions();
Array<double2> positions_2d(positions.size());
threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) {
for (const int i : range) {
positions_2d[i] = double2(positions[i].x, positions[i].y);
}
});
Array<Vector<int>> faces(curves.curves_num());
fill_curve_vert_indices(points_by_curve, faces);
meshintersect::CDT_input<double> input;
input.need_ids = false;
input.vert.reinitialize(points_by_curve.total_size());
input.face.reinitialize(curves.curves_num());
input.vert = std::move(positions_2d);
input.face = std::move(faces);
for (const int i_curve : curves.curves_range()) {
const IndexRange points = points_by_curve[i_curve];
for (const int i : points) {
input.vert[i] = double2(positions[i].x, positions[i].y);
}
input.face[i_curve].resize(points.size());
MutableSpan<int> face_verts = input.face[i_curve];
for (const int i : face_verts.index_range()) {
face_verts[i] = points[i];
}
}
meshintersect::CDT_result<double> result = delaunay_2d_calc(input, output_type);
return result;
return delaunay_2d_calc(input, output_type);
}
static meshintersect::CDT_result<double> do_cdt_with_mask(const bke::CurvesGeometry &curves,
@ -87,34 +94,30 @@ static meshintersect::CDT_result<double> do_cdt_with_mask(const bke::CurvesGeome
const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
const Span<float3> positions = curves.evaluated_positions();
int vert_len = 0;
mask.foreach_index([&](const int i) { vert_len += points_by_curve[i].size(); });
meshintersect::CDT_input<double> input;
input.need_ids = false;
input.vert.reinitialize(vert_len);
input.face.reinitialize(mask.size());
Array<int> offsets_data(mask.size() + 1);
const OffsetIndices points_by_curve_masked = offset_indices::gather_selected_offsets(
points_by_curve, mask, offsets_data);
Array<double2> positions_2d(points_by_curve_masked.total_size());
mask.foreach_index(GrainSize(1024), [&](const int src_curve, const int dst_curve) {
const IndexRange src_points = points_by_curve[src_curve];
const IndexRange dst_points = points_by_curve_masked[dst_curve];
for (const int i : src_points.index_range()) {
const int src = src_points[i];
const int dst = dst_points[i];
input.vert[dst] = double2(positions[src].x, positions[src].y);
positions_2d[dst] = double2(positions[src].x, positions[src].y);
}
input.face[dst_curve].resize(src_points.size());
array_utils::fill_index_range<int>(input.face[dst_curve], dst_points.start());
});
meshintersect::CDT_result<double> result = delaunay_2d_calc(input, output_type);
return result;
Array<Vector<int>> faces(points_by_curve_masked.size());
fill_curve_vert_indices(points_by_curve_masked, faces);
meshintersect::CDT_input<double> input;
input.need_ids = false;
input.vert = std::move(positions_2d);
input.face = std::move(faces);
return delaunay_2d_calc(input, output_type);
}
static Array<meshintersect::CDT_result<double>> do_group_aware_cdt(