Notebook source code: notebooks/how_to/sampler.ipynb
Run it yourself on binder Binder badge

How to sample from a mesh?#

 In [ ]:
import sys
from pathlib import Path

import geomfum
from geomfum.dataset import NotebooksDataset
from geomfum.metric import HeatDistanceMetric
from geomfum.metric.mesh import (
    GraphShortestPathMetric,
    VertexEuclideanMetric,
)
from geomfum.sample import FarthestPointSampler, PoissonSampler, VertexProjectionSampler
from geomfum.shape import TriangleMesh

 In [ ]:
notebooks_dir = Path(geomfum.__file__).resolve().parents[1] / "notebooks"
notebooks_dir_str = str(notebooks_dir)
if notebooks_dir_str not in sys.path:
    sys.path.insert(0, notebooks_dir_str)

from plot_utils import setup_pyvista, show_mesh_with_highlights  # noqa: E402

setup_pyvista()
 In [2]:
dataset = NotebooksDataset()
mesh = TriangleMesh.from_file(dataset.get_filename("cat-00"))

“Coordinate” samplers#

If we’re interested in sampling coordinates of points on the mesh, we can use PoissonSampler.

 In [3]:
poisson_sampler = PoissonSampler.from_registry(min_n_samples=3, which="pymeshlab")
sampled_vertices = poisson_sampler.sample(mesh)
sampled_vertices
 Out [3]:
array([[-0.04288694,  0.37403726,  0.28778169],
       [ 0.03607215,  0.05786218, -0.10858711],
       [-0.04039455,  0.00925685,  0.18873429],
       [ 0.00951004,  0.25221589, -0.43900669],
       [-0.00933553,  0.33280937, -0.01679519]])

Vertex indices samplers#

If we’re interested in sampling vertex indices instead, we can leverage “coordinate” samplers like PoissonSampler by projecting the coordinates to the closest vertices.

 In [4]:
vertex_sampler = VertexProjectionSampler(sampler=poisson_sampler)
sampled_indices = vertex_sampler.sample(mesh)
sampled_indices.astype(int)
 Out [4]:
array([5618, 2377, 4360, 7137,  105,  588])

To get vertex coordinates.

 In [5]:
sampled_vertices = mesh.vertices[sampled_indices]
sampled_vertices
 Out [5]:
array([[ 0.052266,  0.01949 , -0.08939 ],
       [-0.057531,  0.038724,  0.152556],
       [ 0.007673,  0.273714,  0.332385],
       [ 0.008992,  0.253917, -0.39041 ],
       [ 0.053982,  0.263046, -0.139122],
       [-0.026358,  0.318528,  0.094601]])

Let’s visualize the sampled points

 In [6]:
show_mesh_with_highlights(mesh.vertices, mesh.faces, sampled_vertices)

../../_images/notebooks_how_to_sampler_11_0.png

Farthest point sampler#

Alternatively, we can sample vertex indices directly with FarthestPointSampler.

Select the metrics.

 In [7]:
metrics = {
    "euclidean": VertexEuclideanMetric,
    "heat-distance": HeatDistanceMetric,
    "graph": GraphShortestPathMetric,
}

The vertex 7181 corresponds to the extreme of the cat’s tail. We start to sample from this point.

 In [8]:
fps = {}
samp = FarthestPointSampler(
    6,
)

for name, metric in metrics.items():
    mesh.equip_with_metric(metric)
    samples = samp.sample(mesh, first_point=7181)
    fps[name] = samples
    print(f"FPS {name}: {samples}")

FPS euclidean: [7181 4260 6811  404 1625 7080]
FPS heat-distance: [7181 3026 6868 3844 5951 1817]
FPS graph: [7181 4078 5972 7005 1921  402]

Let’s visualize the sampled points

 In [9]:
show_mesh_with_highlights(mesh.vertices, mesh.faces, mesh.vertices[fps["euclidean"]])

../../_images/notebooks_how_to_sampler_18_0.png
 In [10]:
show_mesh_with_highlights(
    mesh.vertices, mesh.faces, mesh.vertices[fps["heat-distance"]]
)

../../_images/notebooks_how_to_sampler_19_0.png
 In [11]:
show_mesh_with_highlights(mesh.vertices, mesh.faces, mesh.vertices[fps["graph"]])

../../_images/notebooks_how_to_sampler_20_0.png

Sampling from a subset#

The vertex 4265 corresponds to the extreme of the cat’s muzzle, i want to select the FPs on the tail.

 In [12]:
points_on_the_tail = list(range(len(mesh.vertices) - 100, len(mesh.vertices)))
 In [13]:
fps = {}
dataset = NotebooksDataset()
samp = FarthestPointSampler(
    6,
)
for name, metric in metrics.items():
    mesh.equip_with_metric(metric)
    samples = samp.sample(mesh, points_pool=points_on_the_tail, first_point=4265)
    fps[name] = samples
    print(f"FPS {name}: {samples}")
C:\Users\giuli\OneDrive\Research\geomfum_proj\geomfum\geomfum\sample.py:76: UserWarning: First index 4265 is not in the points pool [7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120
 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134
 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148
 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162
 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176
 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190
 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204
 7205 7206].
  warnings.warn(
FPS euclidean: [4265 7205 7206 7119 7133 7113]
FPS heat-distance: [4265 7178 7206 7119 7133 7108]
FPS graph: [4265 7192 7206 7122 7132 7113]
 In [14]:
show_mesh_with_highlights(mesh.vertices, mesh.faces, mesh.vertices[fps["euclidean"]])

../../_images/notebooks_how_to_sampler_24_0.png

Further reading#