37
37
LOGGER = scilogger .get_logger (__name__ , "pypeec" )
38
38
39
39
40
+ def _get_voxelize_shape (n , xyz_min , xyz_max , obj ):
41
+ """
42
+ Voxelize a shape with given bounds and voxel numbers.
43
+ """
44
+
45
+ # get the bounds for the voxelization
46
+ (nx , ny , nz ) = n
47
+ (x_min , y_min , z_min ) = xyz_min
48
+ (x_max , y_max , z_max ) = xyz_max
49
+
50
+ # coordinate transformation for the bounds
51
+ transform = rat .from_bounds (x_min , y_max , x_max , y_min , nx , ny )
52
+
53
+ # rasterize the data
54
+ idx_shape = raf .rasterize ([obj ], out_shape = (ny , nx ), transform = transform )
55
+
56
+ # get the boolean matrix with the voxelization result
57
+ idx_shape = np .swapaxes (idx_shape , 0 , 1 )
58
+
59
+ # find the 2D indices
60
+ idx_shape = idx_shape .flatten (order = "F" )
61
+ idx_shape = np .flatnonzero (idx_shape )
62
+
63
+ return idx_shape
64
+
65
+
66
+ def _get_idx_voxel (n , idx_shape , stack_idx ):
67
+ """
68
+ Find the 3D voxel indices from the 2D image indices.
69
+ The number of layers to be added is arbitrary.
70
+ """
71
+
72
+ # get the shape size
73
+ (nx , ny , nz ) = n
74
+
75
+ # init voxel indices
76
+ idx_voxel = np .empty (0 , dtype = np .int64 )
77
+
78
+ # convert image indices into voxel indices
79
+ for idx in stack_idx :
80
+ # convert indices
81
+ idx_tmp = idx * nx * ny + idx_shape
82
+
83
+ # add the indices to the array
84
+ idx_voxel = np .append (idx_voxel , idx_tmp )
85
+
86
+ return idx_voxel
87
+
88
+
40
89
def _get_boundary_polygon (bnd , z_min ):
41
90
"""
42
91
Convert a Shapely boundary into a line mesh.
@@ -150,55 +199,6 @@ def _get_shape_single(tag, shape_type, shape_data):
150
199
return obj
151
200
152
201
153
- def _get_voxelize_shape (n , xyz_min , xyz_max , obj ):
154
- """
155
- Voxelize a shape with given bounds and voxel numbers.
156
- """
157
-
158
- # get the bounds for the voxelization
159
- (nx , ny , nz ) = n
160
- (x_min , y_min , z_min ) = xyz_min
161
- (x_max , y_max , z_max ) = xyz_max
162
-
163
- # coordinate transformation for the bounds
164
- transform = rat .from_bounds (x_min , y_max , x_max , y_min , nx , ny )
165
-
166
- # rasterize the data
167
- idx_shape = raf .rasterize ([obj ], out_shape = (ny , nx ), transform = transform )
168
-
169
- # get the boolean matrix with the voxelization result
170
- idx_shape = np .swapaxes (idx_shape , 0 , 1 )
171
-
172
- # find the 2D indices
173
- idx_shape = idx_shape .flatten (order = "F" )
174
- idx_shape = np .flatnonzero (idx_shape )
175
-
176
- return idx_shape
177
-
178
-
179
- def _get_idx_voxel (n , idx_shape , stack_idx ):
180
- """
181
- Find the 3D voxel indices from the 2D image indices.
182
- The number of layers to be added is arbitrary.
183
- """
184
-
185
- # get the shape size
186
- (nx , ny , nz ) = n
187
-
188
- # init voxel indices
189
- idx_voxel = np .empty (0 , dtype = np .int64 )
190
-
191
- # convert image indices into voxel indices
192
- for idx in stack_idx :
193
- # convert indices
194
- idx_tmp = idx * nx * ny + idx_shape
195
-
196
- # add the indices to the array
197
- idx_voxel = np .append (idx_voxel , idx_tmp )
198
-
199
- return idx_voxel
200
-
201
-
202
202
def _get_shape_assemble (tag , geometry_shape , simplify , construct ):
203
203
"""
204
204
Assemble the shapes (for a specified layer).
@@ -267,44 +267,6 @@ def _get_shape_layer(geometry_shape, stack_tag, simplify, construct):
267
267
return layer_list , obj_list
268
268
269
269
270
- def _get_shape_obj (geometry_shape , stack_tag , simplify , construct ):
271
- """
272
- Create the shapes and set the position in the layer stack.
273
- Find the bounding box for all the shapes (minimum and maximum coordinates).
274
- """
275
-
276
- # init shape list
277
- shape_obj = []
278
-
279
- # init the coordinate (minimum and maximum coordinates)
280
- xy_min = np .full (2 , + np .inf , dtype = np .float64 )
281
- xy_max = np .full (2 , - np .inf , dtype = np .float64 )
282
-
283
- # create the shapes and find the bounding box
284
- for tag , geometry_shape_tmp in geometry_shape .items ():
285
- # get the shape (divided per layer)
286
- (layer_list , obj_list ) = _get_shape_layer (geometry_shape_tmp , stack_tag , simplify , construct )
287
-
288
- # find the layer position and add the objects
289
- for layer , obj in zip (layer_list , obj_list , strict = True ):
290
- # get the stack position
291
- idx = stack_tag .index (layer )
292
-
293
- # find the bounds
294
- (x_min , y_min , x_max , y_max ) = obj .bounds
295
- tmp_min = np .array ((x_min , y_min ), dtype = np .float64 )
296
- tmp_max = np .array ((x_max , y_max ), dtype = np .float64 )
297
-
298
- # update the bounds
299
- xy_min = np .minimum (xy_min , tmp_min )
300
- xy_max = np .maximum (xy_max , tmp_max )
301
-
302
- # assign the object
303
- shape_obj .append ({"tag" : tag , "idx" : idx , "obj" : obj })
304
-
305
- return shape_obj , xy_min , xy_max
306
-
307
-
308
270
def _get_layer_stack (layer_stack , dz , cz ):
309
271
"""
310
272
Parse the layer stack (defined with a list).
@@ -348,36 +310,42 @@ def _get_layer_stack(layer_stack, dz, cz):
348
310
return stack_pos , stack_idx , stack_tag
349
311
350
312
351
- def _get_domain_def ( n , d , c , domain_def , stack_idx , shape_obj ):
313
+ def _get_shape_obj ( geometry_shape , stack_tag , simplify , construct ):
352
314
"""
353
- Voxelize the shapes and assign the indices to a dict.
315
+ Create the shapes and set the position in the layer stack.
316
+ Find the bounding box for all the shapes (minimum and maximum coordinates).
354
317
"""
355
318
356
- # get the voxelization bounds
357
- xyz_min = c - (n * d ) / 2
358
- xyz_max = c + (n * d ) / 2
319
+ # init shape dict
320
+ shape_obj = {}
359
321
360
- # voxelize the shapes
361
- for shape_obj_tmp in shape_obj :
362
- # extract the data
363
- tag = shape_obj_tmp ["tag" ]
364
- obj = shape_obj_tmp ["obj" ]
365
- idx = shape_obj_tmp ["idx" ]
322
+ # init the coordinate (minimum and maximum coordinates)
323
+ xy_min = np .full (2 , + np .inf , dtype = np .float64 )
324
+ xy_max = np .full (2 , - np .inf , dtype = np .float64 )
366
325
367
- # voxelize and get the indices
368
- idx_shape = _get_voxelize_shape (n , xyz_min , xyz_max , obj )
369
- idx_voxel = _get_idx_voxel (n , idx_shape , stack_idx [idx ])
326
+ # create the shapes and find the bounding box
327
+ for tag , geometry_shape_tmp in geometry_shape .items ():
328
+ # get the shape (divided per layer)
329
+ (layer_list , obj_list ) = _get_shape_layer (geometry_shape_tmp , stack_tag , simplify , construct )
370
330
371
- # append the indices into the corresponding domain
372
- domain_def [tag ] = np .append (domain_def [tag ], idx_voxel )
331
+ # find the layer position and add the objects
332
+ for layer , obj in zip (layer_list , obj_list , strict = True ):
333
+ # get the stack position
334
+ idx = stack_tag .index (layer )
373
335
374
- # remove duplicates
375
- for tag , idx_voxel in domain_def .items ():
376
- idx_voxel = np .unique (idx_voxel )
377
- LOGGER .debug ("domain = %s / size = %d" , tag , len (idx_voxel ))
378
- domain_def [tag ] = idx_voxel
336
+ # find the bounds
337
+ (x_min , y_min , x_max , y_max ) = obj .bounds
338
+ tmp_min = np .array ((x_min , y_min ), dtype = np .float64 )
339
+ tmp_max = np .array ((x_max , y_max ), dtype = np .float64 )
379
340
380
- return domain_def
341
+ # update the bounds
342
+ xy_min = np .minimum (xy_min , tmp_min )
343
+ xy_max = np .maximum (xy_max , tmp_max )
344
+
345
+ # assign the object
346
+ shape_obj [tag ] = (obj , idx )
347
+
348
+ return shape_obj , xy_min , xy_max
381
349
382
350
383
351
def _get_voxel_size (dx , dy , dz , stack_pos , xy_max_obj , xy_min_obj , xy_max , xy_min ):
@@ -425,19 +393,15 @@ def _get_voxel_size(dx, dy, dz, stack_pos, xy_max_obj, xy_min_obj, xy_max, xy_mi
425
393
426
394
def _get_merge_shape (stack_pos , shape_obj ):
427
395
"""
428
- Transform all the 2D vector shapes into 3D meshes.
429
- The resulting meshes represent the original geometry.
396
+ Transform all the 2D vector shapes into 3D line meshes.
397
+ The meshes represent the original (non-voxelized) geometry.
430
398
"""
431
399
432
400
# init mesh list
433
401
geom_def = []
434
402
435
403
# merge all the shapes
436
- for shape_obj_tmp in shape_obj :
437
- # extract the data
438
- obj = shape_obj_tmp ["obj" ]
439
- idx = shape_obj_tmp ["idx" ]
440
-
404
+ for obj , idx in shape_obj .values ():
441
405
# get the coordinates
442
406
z_min = stack_pos [idx + 0 ]
443
407
z_max = stack_pos [idx + 1 ]
@@ -454,6 +418,33 @@ def _get_merge_shape(stack_pos, shape_obj):
454
418
return geom_def
455
419
456
420
421
+ def _get_domain_def (n , d , c , domain_def , stack_idx , shape_obj ):
422
+ """
423
+ Voxelize the shapes and assign the indices to a dict.
424
+ """
425
+
426
+ # get the voxelization bounds
427
+ xyz_min = c - (n * d ) / 2
428
+ xyz_max = c + (n * d ) / 2
429
+
430
+ # voxelize the shapes
431
+ for tag , (obj , idx ) in shape_obj .items ():
432
+ # voxelize and get the indices
433
+ idx_shape = _get_voxelize_shape (n , xyz_min , xyz_max , obj )
434
+ idx_voxel = _get_idx_voxel (n , idx_shape , stack_idx [idx ])
435
+
436
+ # append the indices into the corresponding domain
437
+ domain_def [tag ] = np .append (domain_def [tag ], idx_voxel )
438
+
439
+ # remove duplicates
440
+ for tag , idx_voxel in domain_def .items ():
441
+ idx_voxel = np .unique (idx_voxel )
442
+ LOGGER .debug ("domain = %s / size = %d" , tag , len (idx_voxel ))
443
+ domain_def [tag ] = idx_voxel
444
+
445
+ return domain_def
446
+
447
+
457
448
def get_mesh (param , layer_stack , geometry_shape ):
458
449
"""
459
450
Transform a series of 2D vector shapes into a 3D voxel structure.
0 commit comments