Skip to content

Replace VTK's clean filter with our own point merging #79

Open

Description

@akaszynski

Clustering.create_mesh calls VTK's clean filter by default. All we need from it is merging coincident points, but it also rebuilds the cell array, and that undoes the compact representation we hand it.

Measured on 200,000 triangles with an int32, fixed-width cell array:

connectivity fixed-size storage offsets cell array
before clean() int32 yes 1 KiB 2345 KiB
after clean() int64 no 1563 KiB 6251 KiB

So the filter inflates the cell array 2.7x: it widens the connectivity to int64 and materialises an offsets array we had eliminated. On the default clean=True path that means the compact form only ever exists on the intermediate mesh, never on what we return to the caller.

We already have a much better merger in the org. pyvista-stl dedups vertices with a 96-bit hash table (src/hash96.h, Bob Jenkins lookup3, MIT), using a lock-free concurrent open-addressing table on the parallel path with a sequential fallback and mmap-backed allocation (src/stlfile.cpp, roughly lines 316-460). It solves the identical problem, exact coincident-vertex merging over a triangle soup, and it does it while reading the file rather than as a separate pass.

It should transplant cleanly. pyvista-stl and pyacvd already share array_support.h and the same nanobind stack, as does fast-simplification.

Worth doing because:

  • we keep int32 and fixed-width storage through to the returned mesh
  • exact hashing is a better fit than a spatial locator, since the points we merge are bitwise-identical duplicates produced by our own subdivision rather than nearby-but-distinct points
  • it drops a VTK filter from the hot path, and it parallelises

Two things to decide when picking this up. Whether the merge tolerance stays exact or needs to match clean's tolerance behaviour for anyone relying on it, and whether create_mesh(clean=True) keeps that name once it is no longer VTK's clean.

Context: this came out of the in-progress work to make faces int32 and use fixed-width cell storage, which is the representation clean currently discards. I'll link that PR here once it's up.

Activity

  1. akaszynski commented on Aug 15, 2026

    @akaszynski
    MemberAuthor

    The int32 fixed-width work is up as #80. That PR's intermediate arrays halve, but create_mesh(clean=True) still re-widens the returned mesh, which is what this issue would fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions