sdf-sampler 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sdf_sampler/__init__.py +78 -0
- sdf_sampler/algorithms/__init__.py +19 -0
- sdf_sampler/algorithms/flood_fill.py +233 -0
- sdf_sampler/algorithms/normal_idw.py +99 -0
- sdf_sampler/algorithms/normal_offset.py +111 -0
- sdf_sampler/algorithms/pocket.py +146 -0
- sdf_sampler/algorithms/voxel_grid.py +339 -0
- sdf_sampler/algorithms/voxel_regions.py +80 -0
- sdf_sampler/analyzer.py +299 -0
- sdf_sampler/config.py +171 -0
- sdf_sampler/io.py +178 -0
- sdf_sampler/models/__init__.py +49 -0
- sdf_sampler/models/analysis.py +85 -0
- sdf_sampler/models/constraints.py +192 -0
- sdf_sampler/models/samples.py +49 -0
- sdf_sampler/sampler.py +439 -0
- sdf_sampler/sampling/__init__.py +15 -0
- sdf_sampler/sampling/box.py +131 -0
- sdf_sampler/sampling/brush.py +63 -0
- sdf_sampler/sampling/ray_carve.py +134 -0
- sdf_sampler/sampling/sphere.py +57 -0
- sdf_sampler-0.1.0.dist-info/METADATA +226 -0
- sdf_sampler-0.1.0.dist-info/RECORD +25 -0
- sdf_sampler-0.1.0.dist-info/WHEEL +4 -0
- sdf_sampler-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# ABOUTME: Ray carve constraint sampling functions
|
|
2
|
+
# ABOUTME: Generates training samples from ray-scribble interactions
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from sdf_sampler.models.constraints import RayCarveConstraint
|
|
7
|
+
from sdf_sampler.models.samples import TrainingSample
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sample_ray_carve(
|
|
11
|
+
constraint: RayCarveConstraint,
|
|
12
|
+
rng: np.random.Generator,
|
|
13
|
+
n_samples_per_ray: int,
|
|
14
|
+
) -> list[TrainingSample]:
|
|
15
|
+
"""Generate samples from ray-carve constraint.
|
|
16
|
+
|
|
17
|
+
For each ray:
|
|
18
|
+
1. Sample EMPTY points uniformly along ray from origin to (hit - empty_band)
|
|
19
|
+
2. Sample SURFACE points in band around hit point
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
constraint: Ray carve constraint to sample
|
|
23
|
+
rng: Random number generator
|
|
24
|
+
n_samples_per_ray: Number of samples per ray
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
List of TrainingSample objects
|
|
28
|
+
"""
|
|
29
|
+
samples = []
|
|
30
|
+
|
|
31
|
+
# Pre-compute ray data for outlier detection
|
|
32
|
+
ray_data = []
|
|
33
|
+
for ray in constraint.rays:
|
|
34
|
+
origin = np.array(ray.origin)
|
|
35
|
+
direction = np.array(ray.direction)
|
|
36
|
+
direction = direction / np.linalg.norm(direction)
|
|
37
|
+
hit_point = origin + direction * ray.hit_distance
|
|
38
|
+
ray_data.append(
|
|
39
|
+
{
|
|
40
|
+
"origin": origin,
|
|
41
|
+
"direction": direction,
|
|
42
|
+
"hit_distance": ray.hit_distance,
|
|
43
|
+
"hit_point": hit_point,
|
|
44
|
+
"local_spacing": ray.local_spacing,
|
|
45
|
+
"surface_normal": ray.surface_normal,
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Detect outliers: rays that pass through gaps
|
|
50
|
+
effective_hit_distances = []
|
|
51
|
+
for i, ray in enumerate(ray_data):
|
|
52
|
+
effective_dist = ray["hit_distance"]
|
|
53
|
+
|
|
54
|
+
for j, other in enumerate(ray_data):
|
|
55
|
+
if i == j:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
dir_dot = np.dot(ray["direction"], other["direction"])
|
|
59
|
+
if dir_dot > 0.95:
|
|
60
|
+
to_hit = ray["hit_point"] - other["origin"]
|
|
61
|
+
proj_dist = np.dot(to_hit, other["direction"])
|
|
62
|
+
|
|
63
|
+
if proj_dist > other["hit_distance"] * 1.1:
|
|
64
|
+
effective_dist = min(effective_dist, other["hit_distance"])
|
|
65
|
+
|
|
66
|
+
effective_hit_distances.append(effective_dist)
|
|
67
|
+
|
|
68
|
+
for idx, ray in enumerate(ray_data):
|
|
69
|
+
origin = ray["origin"]
|
|
70
|
+
direction = ray["direction"]
|
|
71
|
+
hit_dist = effective_hit_distances[idx]
|
|
72
|
+
|
|
73
|
+
if ray["local_spacing"] is not None:
|
|
74
|
+
buffer_zone = ray["local_spacing"] * constraint.back_buffer_coefficient
|
|
75
|
+
else:
|
|
76
|
+
buffer_zone = constraint.back_buffer_width
|
|
77
|
+
|
|
78
|
+
# EMPTY samples along ray (before hit, stopping at buffer zone)
|
|
79
|
+
empty_end = hit_dist - buffer_zone
|
|
80
|
+
n_empty = n_samples_per_ray // 2
|
|
81
|
+
|
|
82
|
+
if empty_end > 0:
|
|
83
|
+
for _ in range(n_empty):
|
|
84
|
+
t = rng.uniform(0, empty_end)
|
|
85
|
+
point = origin + t * direction
|
|
86
|
+
|
|
87
|
+
samples.append(
|
|
88
|
+
TrainingSample(
|
|
89
|
+
x=float(point[0]),
|
|
90
|
+
y=float(point[1]),
|
|
91
|
+
z=float(point[2]),
|
|
92
|
+
phi=hit_dist - t,
|
|
93
|
+
nx=float(direction[0]),
|
|
94
|
+
ny=float(direction[1]),
|
|
95
|
+
nz=float(direction[2]),
|
|
96
|
+
weight=constraint.weight,
|
|
97
|
+
source="ray_carve_empty",
|
|
98
|
+
is_surface=False,
|
|
99
|
+
is_free=True,
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# SURFACE samples near hit
|
|
104
|
+
n_surface = n_samples_per_ray - n_empty
|
|
105
|
+
for _ in range(n_surface):
|
|
106
|
+
t = rng.uniform(
|
|
107
|
+
hit_dist - constraint.surface_band_width,
|
|
108
|
+
hit_dist,
|
|
109
|
+
)
|
|
110
|
+
point = origin + t * direction
|
|
111
|
+
phi = 0.0
|
|
112
|
+
|
|
113
|
+
if ray["surface_normal"]:
|
|
114
|
+
nx, ny, nz = ray["surface_normal"]
|
|
115
|
+
else:
|
|
116
|
+
nx, ny, nz = -direction[0], -direction[1], -direction[2]
|
|
117
|
+
|
|
118
|
+
samples.append(
|
|
119
|
+
TrainingSample(
|
|
120
|
+
x=float(point[0]),
|
|
121
|
+
y=float(point[1]),
|
|
122
|
+
z=float(point[2]),
|
|
123
|
+
phi=phi,
|
|
124
|
+
nx=float(nx),
|
|
125
|
+
ny=float(ny),
|
|
126
|
+
nz=float(nz),
|
|
127
|
+
weight=constraint.weight,
|
|
128
|
+
source="ray_carve_surface",
|
|
129
|
+
is_surface=True,
|
|
130
|
+
is_free=False,
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
return samples
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# ABOUTME: Sphere constraint sampling functions
|
|
2
|
+
# ABOUTME: Generates training samples from spherical region constraints
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from sdf_sampler.models.constraints import SignConvention, SphereConstraint
|
|
7
|
+
from sdf_sampler.models.samples import TrainingSample
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sample_sphere(
|
|
11
|
+
constraint: SphereConstraint,
|
|
12
|
+
rng: np.random.Generator,
|
|
13
|
+
near_band: float,
|
|
14
|
+
n_samples: int,
|
|
15
|
+
) -> list[TrainingSample]:
|
|
16
|
+
"""Generate samples from a sphere constraint.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
constraint: Sphere constraint to sample
|
|
20
|
+
rng: Random number generator
|
|
21
|
+
near_band: Near-band width for offset
|
|
22
|
+
n_samples: Number of samples to generate
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
List of TrainingSample objects
|
|
26
|
+
"""
|
|
27
|
+
samples = []
|
|
28
|
+
center = np.array(constraint.center)
|
|
29
|
+
radius = constraint.radius
|
|
30
|
+
|
|
31
|
+
for _ in range(n_samples):
|
|
32
|
+
direction = rng.standard_normal(3)
|
|
33
|
+
direction /= np.linalg.norm(direction)
|
|
34
|
+
|
|
35
|
+
point = center + radius * direction
|
|
36
|
+
|
|
37
|
+
offset = near_band if constraint.sign == SignConvention.EMPTY else -near_band
|
|
38
|
+
point = point + offset * direction
|
|
39
|
+
phi = offset
|
|
40
|
+
|
|
41
|
+
samples.append(
|
|
42
|
+
TrainingSample(
|
|
43
|
+
x=float(point[0]),
|
|
44
|
+
y=float(point[1]),
|
|
45
|
+
z=float(point[2]),
|
|
46
|
+
phi=phi,
|
|
47
|
+
nx=float(direction[0]),
|
|
48
|
+
ny=float(direction[1]),
|
|
49
|
+
nz=float(direction[2]),
|
|
50
|
+
weight=constraint.weight,
|
|
51
|
+
source=f"sphere_{constraint.sign.value}",
|
|
52
|
+
is_surface=False,
|
|
53
|
+
is_free=constraint.sign == SignConvention.EMPTY,
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return samples
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sdf-sampler
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Auto-analysis and sampling of point clouds for SDF (Signed Distance Field) training data generation
|
|
5
|
+
Project-URL: Repository, https://github.com/chiark/sdf-sampler
|
|
6
|
+
Author-email: Liam <liam@example.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: machine-learning,point-cloud,sampling,sdf,signed-distance-field
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: alphashape>=1.3.1
|
|
21
|
+
Requires-Dist: numpy>=1.26.0
|
|
22
|
+
Requires-Dist: pandas>=2.1.0
|
|
23
|
+
Requires-Dist: pyarrow>=14.0.0
|
|
24
|
+
Requires-Dist: pydantic>=2.5.0
|
|
25
|
+
Requires-Dist: scipy>=1.11.0
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: laspy[laszip]>=2.5.0; extra == 'all'
|
|
28
|
+
Requires-Dist: mypy>=1.8.0; extra == 'all'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
|
|
31
|
+
Requires-Dist: pytest>=8.0.0; extra == 'all'
|
|
32
|
+
Requires-Dist: ruff>=0.5.0; extra == 'all'
|
|
33
|
+
Requires-Dist: trimesh>=4.0.0; extra == 'all'
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: ruff>=0.5.0; extra == 'dev'
|
|
40
|
+
Provides-Extra: io
|
|
41
|
+
Requires-Dist: laspy[laszip]>=2.5.0; extra == 'io'
|
|
42
|
+
Requires-Dist: trimesh>=4.0.0; extra == 'io'
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# sdf-sampler
|
|
46
|
+
|
|
47
|
+
Auto-analysis and sampling of point clouds for SDF (Signed Distance Field) training data generation.
|
|
48
|
+
|
|
49
|
+
A lightweight, standalone Python package for generating SDF training hints from point clouds. Automatically detects SOLID (inside) and EMPTY (outside) regions and generates training samples suitable for SDF regression models.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install sdf-sampler
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For additional I/O format support (PLY, LAS/LAZ):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install sdf-sampler[io]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from sdf_sampler import SDFAnalyzer, SDFSampler, load_point_cloud
|
|
67
|
+
|
|
68
|
+
# 1. Load point cloud (supports PLY, LAS, CSV, NPZ, Parquet)
|
|
69
|
+
xyz, normals = load_point_cloud("scan.ply")
|
|
70
|
+
|
|
71
|
+
# 2. Auto-analyze to detect EMPTY/SOLID regions
|
|
72
|
+
analyzer = SDFAnalyzer()
|
|
73
|
+
result = analyzer.analyze(xyz=xyz, normals=normals)
|
|
74
|
+
print(f"Generated {len(result.constraints)} constraints")
|
|
75
|
+
|
|
76
|
+
# 3. Generate training samples
|
|
77
|
+
sampler = SDFSampler()
|
|
78
|
+
samples = sampler.generate(
|
|
79
|
+
xyz=xyz,
|
|
80
|
+
constraints=result.constraints,
|
|
81
|
+
strategy="inverse_square",
|
|
82
|
+
total_samples=50000,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# 4. Export to parquet
|
|
86
|
+
sampler.export_parquet(samples, "training_data.parquet")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Features
|
|
90
|
+
|
|
91
|
+
### Auto-Analysis Algorithms
|
|
92
|
+
|
|
93
|
+
- **flood_fill**: Detects EMPTY (outside) regions by ray propagation from sky
|
|
94
|
+
- **voxel_regions**: Detects SOLID (underground) regions
|
|
95
|
+
- **normal_offset**: Generates paired SOLID/EMPTY boxes along surface normals
|
|
96
|
+
- **normal_idw**: Inverse distance weighted sampling along normals
|
|
97
|
+
- **pocket**: Detects interior cavities
|
|
98
|
+
|
|
99
|
+
### Sampling Strategies
|
|
100
|
+
|
|
101
|
+
- **CONSTANT**: Fixed number of samples per constraint
|
|
102
|
+
- **DENSITY**: Samples proportional to constraint volume
|
|
103
|
+
- **INVERSE_SQUARE**: More samples near surface, fewer far away (recommended)
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
### SDFAnalyzer
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from sdf_sampler import SDFAnalyzer, AnalyzerConfig
|
|
111
|
+
|
|
112
|
+
# With default config
|
|
113
|
+
analyzer = SDFAnalyzer()
|
|
114
|
+
|
|
115
|
+
# With custom config
|
|
116
|
+
analyzer = SDFAnalyzer(config=AnalyzerConfig(
|
|
117
|
+
min_gap_size=0.10, # Minimum gap for flood fill
|
|
118
|
+
max_grid_dim=200, # Maximum voxel grid dimension
|
|
119
|
+
cone_angle=15.0, # Ray propagation cone angle
|
|
120
|
+
hull_filter_enabled=True, # Filter outside X-Y hull
|
|
121
|
+
))
|
|
122
|
+
|
|
123
|
+
# Run analysis
|
|
124
|
+
result = analyzer.analyze(
|
|
125
|
+
xyz=xyz, # (N, 3) point positions
|
|
126
|
+
normals=normals, # (N, 3) point normals (optional)
|
|
127
|
+
algorithms=["flood_fill", "voxel_regions"], # Which algorithms to run
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Access results
|
|
131
|
+
print(f"Total constraints: {result.summary.total_constraints}")
|
|
132
|
+
print(f"SOLID: {result.summary.solid_constraints}")
|
|
133
|
+
print(f"EMPTY: {result.summary.empty_constraints}")
|
|
134
|
+
|
|
135
|
+
# Get constraint dicts for sampling
|
|
136
|
+
constraints = result.constraints
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### SDFSampler
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from sdf_sampler import SDFSampler, SamplerConfig
|
|
143
|
+
|
|
144
|
+
# With default config
|
|
145
|
+
sampler = SDFSampler()
|
|
146
|
+
|
|
147
|
+
# With custom config
|
|
148
|
+
sampler = SDFSampler(config=SamplerConfig(
|
|
149
|
+
total_samples=10000,
|
|
150
|
+
inverse_square_base_samples=100,
|
|
151
|
+
inverse_square_falloff=2.0,
|
|
152
|
+
near_band=0.02,
|
|
153
|
+
))
|
|
154
|
+
|
|
155
|
+
# Generate samples
|
|
156
|
+
samples = sampler.generate(
|
|
157
|
+
xyz=xyz, # Point cloud for distance computation
|
|
158
|
+
constraints=constraints, # From analyzer.analyze().constraints
|
|
159
|
+
strategy="inverse_square", # Sampling strategy
|
|
160
|
+
seed=42, # For reproducibility
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Export
|
|
164
|
+
sampler.export_parquet(samples, "output.parquet")
|
|
165
|
+
|
|
166
|
+
# Or get DataFrame
|
|
167
|
+
df = sampler.to_dataframe(samples)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Constraint Types
|
|
171
|
+
|
|
172
|
+
The analyzer generates various constraint types:
|
|
173
|
+
|
|
174
|
+
- **BoxConstraint**: Axis-aligned bounding box
|
|
175
|
+
- **SphereConstraint**: Spherical region
|
|
176
|
+
- **SamplePointConstraint**: Direct point with signed distance
|
|
177
|
+
- **PocketConstraint**: Detected cavity region
|
|
178
|
+
|
|
179
|
+
Each constraint has:
|
|
180
|
+
- `sign`: "solid" (negative SDF) or "empty" (positive SDF)
|
|
181
|
+
- `weight`: Sample weight (default 1.0)
|
|
182
|
+
|
|
183
|
+
## Output Format
|
|
184
|
+
|
|
185
|
+
The exported parquet file contains columns:
|
|
186
|
+
|
|
187
|
+
| Column | Type | Description |
|
|
188
|
+
|--------|------|-------------|
|
|
189
|
+
| x, y, z | float | 3D position |
|
|
190
|
+
| phi | float | Signed distance (negative=solid, positive=empty) |
|
|
191
|
+
| nx, ny, nz | float | Normal vector (if available) |
|
|
192
|
+
| weight | float | Sample weight |
|
|
193
|
+
| source | string | Sample origin (e.g., "box_solid", "flood_fill_empty") |
|
|
194
|
+
| is_surface | bool | Whether sample is on surface |
|
|
195
|
+
| is_free | bool | Whether sample is in free space (EMPTY) |
|
|
196
|
+
|
|
197
|
+
## Configuration Options
|
|
198
|
+
|
|
199
|
+
### AnalyzerConfig
|
|
200
|
+
|
|
201
|
+
| Option | Default | Description |
|
|
202
|
+
|--------|---------|-------------|
|
|
203
|
+
| min_gap_size | 0.10 | Minimum gap size for flood fill (meters) |
|
|
204
|
+
| max_grid_dim | 200 | Maximum voxel grid dimension |
|
|
205
|
+
| cone_angle | 15.0 | Ray propagation cone half-angle (degrees) |
|
|
206
|
+
| normal_offset_pairs | 40 | Number of box pairs for normal_offset |
|
|
207
|
+
| idw_sample_count | 1000 | Total IDW samples |
|
|
208
|
+
| idw_max_distance | 0.5 | Maximum IDW distance (meters) |
|
|
209
|
+
| hull_filter_enabled | True | Filter outside X-Y alpha shape |
|
|
210
|
+
| hull_alpha | 1.0 | Alpha shape parameter |
|
|
211
|
+
|
|
212
|
+
### SamplerConfig
|
|
213
|
+
|
|
214
|
+
| Option | Default | Description |
|
|
215
|
+
|--------|---------|-------------|
|
|
216
|
+
| total_samples | 10000 | Default total samples |
|
|
217
|
+
| samples_per_primitive | 100 | Samples per constraint (CONSTANT) |
|
|
218
|
+
| samples_per_cubic_meter | 10000 | Sample density (DENSITY) |
|
|
219
|
+
| inverse_square_base_samples | 100 | Base samples (INVERSE_SQUARE) |
|
|
220
|
+
| inverse_square_falloff | 2.0 | Falloff exponent |
|
|
221
|
+
| near_band | 0.02 | Near-band width |
|
|
222
|
+
| seed | 0 | Random seed |
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
sdf_sampler/__init__.py,sha256=9LyfRS8RsgknQvp5TKUKKknuQD9Ovm74qlfbxlOvfCE,1891
|
|
2
|
+
sdf_sampler/analyzer.py,sha256=p5Pkoa01dBGFqqQs2wpWrr8ilPMsjkB4ODJEI2IWbdo,11674
|
|
3
|
+
sdf_sampler/config.py,sha256=lrPM1ktFkv32RRtOz6R-ShUFlBZ2LvoAl1hRLThmgKw,5185
|
|
4
|
+
sdf_sampler/io.py,sha256=DfdXJa_2KQhja_T_a-jlVADcAABeF-NR8e3_vnIJHnk,4968
|
|
5
|
+
sdf_sampler/sampler.py,sha256=QVrI1TxfnSgQWYcJdRCEQqvFekPvFBUYJfrbjQj-ABY,15551
|
|
6
|
+
sdf_sampler/algorithms/__init__.py,sha256=pp7tSZ8q0zRXZ5S8D3tho7bJ62pmW8jceuuRXtiXIzU,777
|
|
7
|
+
sdf_sampler/algorithms/flood_fill.py,sha256=iWGPPtOPSs0Cg7pxUlXUKGloFNCr8PuCHguRNy3c56c,7042
|
|
8
|
+
sdf_sampler/algorithms/normal_idw.py,sha256=uX3MQDTDX0wVilwxDE9dFj9hm2xuBDHV-AZqspjz7sk,3270
|
|
9
|
+
sdf_sampler/algorithms/normal_offset.py,sha256=SzWMaK_Ws2Bg-vu_b5_viCEqJts92ezdXaFfhE97RaE,3712
|
|
10
|
+
sdf_sampler/algorithms/pocket.py,sha256=d6cvFz8C1ZFGgaOEySnFcKMPlHZ-kqOU_bBvOoXTUpw,4978
|
|
11
|
+
sdf_sampler/algorithms/voxel_grid.py,sha256=LJz5V02AxSBRL0-kNEV3yEN_cMWFymGiepX0yysE6dw,11133
|
|
12
|
+
sdf_sampler/algorithms/voxel_regions.py,sha256=YHr-apdq9wTo_po6v5L9HxQLkcZ1kP3KfJhoaQDZJOE,2422
|
|
13
|
+
sdf_sampler/models/__init__.py,sha256=XWzMnPgvZyZF1ZUSfqlspIitLkzMn_0Yxj-hRF-ALEQ,1134
|
|
14
|
+
sdf_sampler/models/analysis.py,sha256=h9CIxBeTQ89Z2-B3qdrlHM8qtOA0caijTYwzd9HsyUw,3251
|
|
15
|
+
sdf_sampler/models/constraints.py,sha256=k0v6-JwXmUkFXGycDpPG44amjoRo13xz1ggqdr9NVtE,7316
|
|
16
|
+
sdf_sampler/models/samples.py,sha256=0DD7Z8D70zJKRTq16pik9SgGiRDeXh56EqmBZfql_sk,1474
|
|
17
|
+
sdf_sampler/sampling/__init__.py,sha256=mbeU9DTHxR4R1D4WqjEzaYHq7bV1nSv-wywc3YoD_Lg,492
|
|
18
|
+
sdf_sampler/sampling/box.py,sha256=qRAumR1z_7vU9rfNvk-B6xNu62UeHSyQNghYiTwVR_Y,3912
|
|
19
|
+
sdf_sampler/sampling/brush.py,sha256=CcAgOYLdYXMM3y_H4fIwyzRJ8PZivFxkUHP7d0ElpNM,1991
|
|
20
|
+
sdf_sampler/sampling/ray_carve.py,sha256=EsfzEGk33q0iWVzOJKDAJi2iWEsY-JZXmEfEZ0dmNdg,4444
|
|
21
|
+
sdf_sampler/sampling/sphere.py,sha256=Xqpwq-RcEnAD6HhoyIC-ErxRHDknDKMtYf6aWUJ43_U,1680
|
|
22
|
+
sdf_sampler-0.1.0.dist-info/METADATA,sha256=CygvgjodkmWtCsBMMXz1MLEGufR1XGZUSabpA7dII-w,7165
|
|
23
|
+
sdf_sampler-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
24
|
+
sdf_sampler-0.1.0.dist-info/licenses/LICENSE,sha256=eeB8aLnEG-dgFYs2KqfMJaP52GFQT8sZPHwaYnHRW8E,1061
|
|
25
|
+
sdf_sampler-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Liam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|