Coverage for src/meshpy/mesh_creation_functions/nurbs_generic.py: 97%

186 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-28 04:21 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2018-2025 MeshPy Authors 

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 

13# all 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 

21# THE SOFTWARE. 

22"""Generic function used to create NURBS meshes within meshpy.""" 

23 

24import numpy as _np 

25 

26from meshpy.core.conf import mpy as _mpy 

27from meshpy.core.geometry_set import GeometryName as _GeometryName 

28from meshpy.core.geometry_set import GeometrySetNodes as _GeometrySetNodes 

29from meshpy.core.node import ControlPoint as _ControlPoint 

30from meshpy.core.nurbs_patch import NURBSSurface as _NURBSSurface 

31from meshpy.core.nurbs_patch import NURBSVolume as _NURBSVolume 

32 

33 

34def add_geomdl_nurbs_to_mesh( 

35 mesh, 

36 geomdl_obj, 

37 *, 

38 material=None, 

39 element_string=None, 

40 element_description=None, 

41): 

42 """Generic NURBS mesh creation function. 

43 

44 Args 

45 ---- 

46 mesh: Mesh 

47 Mesh that the created NURBS geometry should be added to. 

48 geomdl_obj: Geomdl object 

49 NURBS geometry created using Geomdl. 

50 material: Material 

51 Material for this geometry. 

52 element_description: 

53 Information that will be written after the information of 

54 the elements. 

55 

56 Return 

57 ---- 

58 return_set: GeometryName 

59 Set with the control points that form the topology of the mesh. 

60 

61 For a surface, the following information is stored: 

62 Vertices: 'vertex_u_min_v_min', 'vertex_u_max_v_min', 'vertex_u_min_v_max', 'vertex_u_max_v_max' 

63 Edges: 'line_v_min', 'line_u_max', 'line_v_max', 'line_u_min' 

64 Surface: 'surf' 

65 

66 For a volume, the following information is stored: 

67 Vertices: 'vertex_u_min_v_min_w_min', 'vertex_u_max_v_min_w_min', 'vertex_u_min_v_max_w_min', 'vertex_u_max_v_max_w_min', 

68 'vertex_u_min_v_min_w_max', 'vertex_u_max_v_min_w_max', 'vertex_u_min_v_max_w_max', 'vertex_u_max_v_max_w_max' 

69 Edges: 'line_v_min_w_min', 'line_u_max_w_min', 'line_v_max_w_min', 'line_u_min_w_min', 

70 'line_u_min_v_min', 'line_u_max_v_min', 'line_u_min_v_max', 'line_u_max_v_max' 

71 'line_v_min_w_max', 'line_u_max_w_max', 'line_v_max_w_max', 'line_u_min_w_max' 

72 Surfaces: 'surf_w_min', 'surf_w_max', 'surf_v_min', 'surf_v_max', 'surf_v_max', 'surf_u_min' 

73 Volume: 'vol' 

74 """ 

75 

76 # Make sure the material is in the mesh 

77 mesh.add_material(material) 

78 

79 # Fill control points 

80 control_points = [] 

81 nurbs_dimension = len(geomdl_obj.knotvector) 

82 if nurbs_dimension == 2: 

83 control_points = create_control_points_surface(geomdl_obj) 

84 elif nurbs_dimension == 3: 

85 control_points = create_control_points_volume(geomdl_obj) 

86 else: 

87 raise NotImplementedError( 

88 "Error, not implemented for NURBS with dimension {}!".format( 

89 nurbs_dimension 

90 ) 

91 ) 

92 

93 # Fill element 

94 manifold_dim = len(geomdl_obj.knotvector) 

95 

96 if manifold_dim == 2: 

97 nurbs_object = _NURBSSurface 

98 elif manifold_dim == 3: 

99 nurbs_object = _NURBSVolume 

100 else: 

101 raise NotImplementedError( 

102 "Error, not implemented for a NURBS {}!".format(type(geomdl_obj)) 

103 ) 

104 

105 element = nurbs_object( 

106 geomdl_obj.knotvector, 

107 geomdl_obj.degree, 

108 nodes=control_points, 

109 material=material, 

110 element_string=element_string, 

111 element_description=element_description, 

112 ) 

113 

114 # Add element and control points to the mesh 

115 mesh.elements.append(element) 

116 mesh.nodes.extend(control_points) 

117 

118 # Create geometry sets that will be returned 

119 return_set = create_geometry_sets(element) 

120 

121 return return_set 

122 

123 

124def create_control_points_surface(geomdl_obj): 

125 """Creates a list with the ControlPoint objects of a surface created with 

126 geomdl.""" 

127 control_points = [] 

128 for dir_v in range(geomdl_obj.ctrlpts_size_v): 

129 for dir_u in range(geomdl_obj.ctrlpts_size_u): 

130 weight = geomdl_obj.ctrlpts2d[dir_u][dir_v][3] 

131 

132 # As the control points are scaled with their weight, divide them to get 

133 # their coordinates 

134 coord = [ 

135 geomdl_obj.ctrlpts2d[dir_u][dir_v][0] / weight, 

136 geomdl_obj.ctrlpts2d[dir_u][dir_v][1] / weight, 

137 geomdl_obj.ctrlpts2d[dir_u][dir_v][2] / weight, 

138 ] 

139 

140 control_points.append(_ControlPoint(coord, weight)) 

141 

142 return control_points 

143 

144 

145def create_control_points_volume(geomdl_obj): 

146 """Creates a list with the ControlPoint objects of a volume created with 

147 geomdl.""" 

148 control_points = [] 

149 for dir_w in range(geomdl_obj.ctrlpts_size_w): 

150 for dir_v in range(geomdl_obj.ctrlpts_size_v): 

151 for dir_u in range(geomdl_obj.ctrlpts_size_u): 

152 # Obtain the id of the control point 

153 cp_id = ( 

154 dir_v 

155 + geomdl_obj.ctrlpts_size_v * dir_u 

156 + geomdl_obj.ctrlpts_size_u * geomdl_obj.ctrlpts_size_v * dir_w 

157 ) 

158 

159 weight = geomdl_obj.ctrlptsw[cp_id][3] 

160 

161 # As the control points are scaled with their weight, divide them to get 

162 # their coordinates 

163 coord = [ 

164 geomdl_obj.ctrlptsw[cp_id][0] / weight, 

165 geomdl_obj.ctrlptsw[cp_id][1] / weight, 

166 geomdl_obj.ctrlptsw[cp_id][2] / weight, 

167 ] 

168 

169 control_points.append(_ControlPoint(coord, weight)) 

170 

171 return control_points 

172 

173 

174def create_geometry_sets(element): 

175 """Function that returns a GeometryName object. 

176 

177 For more information of the return item, look into 

178 add_geomdl_nurbs_to_mesh. 

179 """ 

180 

181 def get_num_cps_uvw(knot_vectors): 

182 """Obtain the number of control points on each parametric direction of 

183 a patch.""" 

184 num_cps_uvw = _np.zeros(len(knot_vectors), dtype=int) 

185 

186 for direction in range(len(knot_vectors)): 

187 knotvector_size_dir = len(element.knot_vectors[direction]) 

188 p_dir = element.polynomial_orders[direction] 

189 cp_size_dir = knotvector_size_dir - p_dir - 1 

190 

191 num_cps_uvw[direction] = cp_size_dir 

192 

193 return num_cps_uvw 

194 

195 def get_patch_vertices(return_set, num_cps_uvw, nurbs_dimension, element): 

196 """Get the control points positioned over the vertices of a patch.""" 

197 

198 if nurbs_dimension == 2: 

199 # Vertex 1 is positioned on u = 0, v = 0 

200 return_set["vertex_u_min_v_min"] = _GeometrySetNodes( 

201 _mpy.geo.point, nodes=element.nodes[0] 

202 ) 

203 

204 # Vertex 2 is positioned on u = 1, v = 0 

205 return_set["vertex_u_max_v_min"] = _GeometrySetNodes( 

206 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] - 1] 

207 ) 

208 

209 # Vertex 3 is positioned on u = 0, v = 1 

210 return_set["vertex_u_min_v_max"] = _GeometrySetNodes( 

211 _mpy.geo.point, 

212 nodes=element.nodes[num_cps_uvw[0] * (num_cps_uvw[1] - 1)], 

213 ) 

214 

215 # Vertex 4 is positioned on u = 1, v = 1 

216 return_set["vertex_u_max_v_max"] = _GeometrySetNodes( 

217 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] * num_cps_uvw[1] - 1] 

218 ) 

219 

220 elif nurbs_dimension == 3: 

221 # Vertex 1 is positioned on u = 0, v = 0, w = 

222 return_set["vertex_u_min_v_min_w_min"] = _GeometrySetNodes( 

223 _mpy.geo.point, nodes=element.nodes[0] 

224 ) 

225 

226 # Vertex 2 is positioned on u = 1, v = 0, w = 0 

227 return_set["vertex_u_max_v_min_w_min"] = _GeometrySetNodes( 

228 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] - 1] 

229 ) 

230 

231 # Vertex 3 is positioned on u = 0, v = 1, w = 0 

232 return_set["vertex_u_min_v_max_w_min"] = _GeometrySetNodes( 

233 _mpy.geo.point, 

234 nodes=element.nodes[num_cps_uvw[0] * (num_cps_uvw[1] - 1)], 

235 ) 

236 

237 # Vertex 4 is positioned on u = 1, v = 1, w = 0 

238 return_set["vertex_u_max_v_max_w_min"] = _GeometrySetNodes( 

239 _mpy.geo.point, nodes=element.nodes[num_cps_uvw[0] * num_cps_uvw[1] - 1] 

240 ) 

241 

242 # Vertex 5 is positioned on u = 0, v = 0, w = 1 

243 return_set["vertex_u_min_v_min_w_max"] = _GeometrySetNodes( 

244 _mpy.geo.point, 

245 nodes=element.nodes[ 

246 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

247 ], 

248 ) 

249 

250 # Vertex 6 is positioned on u = 1, v = 0, w = 1 

251 return_set["vertex_u_max_v_min_w_max"] = _GeometrySetNodes( 

252 _mpy.geo.point, 

253 nodes=element.nodes[ 

254 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

255 + (num_cps_uvw[0] - 1) 

256 ], 

257 ) 

258 

259 # Vertex 7 is positioned on u = 0, v = 1, w = 1 

260 return_set["vertex_u_min_v_max_w_max"] = _GeometrySetNodes( 

261 _mpy.geo.point, 

262 nodes=element.nodes[ 

263 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

264 + num_cps_uvw[0] * (num_cps_uvw[1] - 1) 

265 ], 

266 ) 

267 

268 # Vertex 8 is positioned on u = 1, v = 1, w = 1 

269 return_set["vertex_u_max_v_max_w_max"] = _GeometrySetNodes( 

270 _mpy.geo.point, 

271 nodes=element.nodes[ 

272 num_cps_uvw[0] * num_cps_uvw[1] * num_cps_uvw[2] - 1 

273 ], 

274 ) 

275 

276 else: 

277 raise NotImplementedError( 

278 "Error, not implemented for NURBS with dimension {}!".format( 

279 nurbs_dimension 

280 ) 

281 ) 

282 

283 def get_patch_lines(return_set, num_cps_uvw, nurbs_dimension, element): 

284 """Get the control points positioned over the lines of a patch.""" 

285 

286 if nurbs_dimension == 2: 

287 name_dir = ["v", "u"] 

288 name_other_dir = ["min", "min_next", "max_next", "max"] 

289 

290 for i_dir, i_other_dir in ((0, 1), (1, 0)): 

291 n_cp_dir = num_cps_uvw[i_dir] 

292 n_cp_other_dir = num_cps_uvw[i_other_dir] 

293 factor_dir = 1 if i_dir == 0 else n_cp_other_dir 

294 factor_other_dir = n_cp_dir if i_dir == 0 else 1 

295 

296 for index, i_along_other_dir in enumerate( 

297 ( 

298 0, 

299 1, 

300 n_cp_other_dir - 2, 

301 n_cp_other_dir - 1, 

302 ) 

303 ): 

304 cp_indices = [] 

305 for i_along_dir in range(n_cp_dir): 

306 cp_indices.append( 

307 i_along_other_dir * factor_other_dir 

308 + i_along_dir * factor_dir 

309 ) 

310 set_name = f"line_{name_dir[i_dir]}_{name_other_dir[index]}" 

311 return_set[set_name] = _GeometrySetNodes( 

312 _mpy.geo.line, 

313 nodes=[element.nodes[i_node] for i_node in cp_indices], 

314 ) 

315 

316 elif nurbs_dimension == 3: 

317 # Define the rest of the lines to define a volume 

318 control_points_line_1 = [] 

319 control_points_line_2 = [] 

320 control_points_line_3 = [] 

321 control_points_line_4 = [] 

322 control_points_line_5 = [] 

323 control_points_line_6 = [] 

324 control_points_line_7 = [] 

325 control_points_line_8 = [] 

326 control_points_line_9 = [] 

327 control_points_line_10 = [] 

328 control_points_line_11 = [] 

329 control_points_line_12 = [] 

330 

331 # Fill line 1, 3, 9 and 11 with their control points 

332 for i in range(num_cps_uvw[0]): 

333 # Line 1 has the control points on u = [0,1], v = 0, w = 0 

334 cpgid_l1 = num_cps_uvw[0] * 0 + i 

335 control_points_line_1.append(element.nodes[cpgid_l1]) 

336 

337 # Line 3 has the control points on u = [0,1], v = 1, w = 0 

338 cpgid_l3 = num_cps_uvw[0] * (num_cps_uvw[1] - 1) + i 

339 control_points_line_3.append(element.nodes[cpgid_l3]) 

340 

341 # Line 9 has the control points on u = [0,1], v = 0, w = 1 

342 cpgid_l9 = num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) + i 

343 control_points_line_9.append(element.nodes[cpgid_l9]) 

344 

345 # Line 11 has the control points on u = [0,1], v = 1, w = 1 

346 cpgid_l11 = ( 

347 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

348 + num_cps_uvw[0] * (num_cps_uvw[1] - 1) 

349 + i 

350 ) 

351 control_points_line_11.append(element.nodes[cpgid_l11]) 

352 

353 # Fill line 2, 4, 10 and 12 with their control points 

354 for j in range(num_cps_uvw[1]): 

355 # Line 2 has the control points on u = 1, v = [0,1] , w = 0 

356 cpgid_l2 = num_cps_uvw[0] * j + (num_cps_uvw[0] - 1) 

357 control_points_line_2.append(element.nodes[cpgid_l2]) 

358 

359 # Line 4 has the control points on u = 0, v = [0,1] , w = 0 

360 cpgid_l4 = num_cps_uvw[0] * j + 0 

361 control_points_line_4.append(element.nodes[cpgid_l4]) 

362 

363 # Line 10 has the control points on u = 1, v = [0,1] , w = 1 

364 cpgid_l10 = ( 

365 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

366 + num_cps_uvw[0] * j 

367 + (num_cps_uvw[0] - 1) 

368 ) 

369 control_points_line_10.append(element.nodes[cpgid_l10]) 

370 

371 # Line 12 has the control points on u = 0, v = [0,1] , w = 1 

372 cpgid_l12 = ( 

373 num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1) 

374 + num_cps_uvw[0] * j 

375 ) 

376 control_points_line_12.append(element.nodes[cpgid_l12]) 

377 

378 # Fill line 5, 6, 7 and 8 with their control points 

379 for k in range(num_cps_uvw[2]): 

380 # Line 5 has the control points on u = 0, v = 0 , w = [0,1] 

381 cpgid_l5 = num_cps_uvw[0] * num_cps_uvw[1] * k 

382 control_points_line_5.append(element.nodes[cpgid_l5]) 

383 

384 # Line 6 has the control points on u = 1, v = 0 , w = [0,1] 

385 cpgid_l6 = num_cps_uvw[0] * num_cps_uvw[1] * k + num_cps_uvw[0] - 1 

386 control_points_line_6.append(element.nodes[cpgid_l6]) 

387 

388 # Line 7 has the control points on u = 0, v = 1 , w = [0,1] 

389 cpgid_l7 = num_cps_uvw[0] * num_cps_uvw[1] * k + num_cps_uvw[0] * ( 

390 num_cps_uvw[1] - 1 

391 ) 

392 control_points_line_7.append(element.nodes[cpgid_l7]) 

393 

394 # Line 8 has the control points on u = 1, v = 1 , w = [0,1] 

395 cpgid_l8 = ( 

396 num_cps_uvw[0] * num_cps_uvw[1] * k 

397 + num_cps_uvw[0] * num_cps_uvw[1] 

398 - 1 

399 ) 

400 control_points_line_8.append(element.nodes[cpgid_l8]) 

401 

402 # Create geometric sets for lines 

403 return_set["line_v_min_w_min"] = _GeometrySetNodes( 

404 _mpy.geo.line, nodes=control_points_line_1 

405 ) 

406 return_set["line_u_max_w_min"] = _GeometrySetNodes( 

407 _mpy.geo.line, nodes=control_points_line_2 

408 ) 

409 return_set["line_v_max_w_min"] = _GeometrySetNodes( 

410 _mpy.geo.line, nodes=control_points_line_3 

411 ) 

412 return_set["line_u_min_w_min"] = _GeometrySetNodes( 

413 _mpy.geo.line, nodes=control_points_line_4 

414 ) 

415 return_set["line_u_min_v_min"] = _GeometrySetNodes( 

416 _mpy.geo.line, nodes=control_points_line_5 

417 ) 

418 return_set["line_u_max_v_min"] = _GeometrySetNodes( 

419 _mpy.geo.line, nodes=control_points_line_6 

420 ) 

421 return_set["line_u_min_v_max"] = _GeometrySetNodes( 

422 _mpy.geo.line, nodes=control_points_line_7 

423 ) 

424 return_set["line_u_max_v_max"] = _GeometrySetNodes( 

425 _mpy.geo.line, nodes=control_points_line_8 

426 ) 

427 return_set["line_v_min_w_max"] = _GeometrySetNodes( 

428 _mpy.geo.line, nodes=control_points_line_9 

429 ) 

430 return_set["line_u_max_w_max"] = _GeometrySetNodes( 

431 _mpy.geo.line, nodes=control_points_line_10 

432 ) 

433 return_set["line_v_max_w_max"] = _GeometrySetNodes( 

434 _mpy.geo.line, nodes=control_points_line_11 

435 ) 

436 return_set["line_u_min_w_max"] = _GeometrySetNodes( 

437 _mpy.geo.line, nodes=control_points_line_12 

438 ) 

439 

440 else: 

441 raise NotImplementedError( 

442 "Error, not implemented for NURBS with dimension {}!".format( 

443 nurbs_dimension 

444 ) 

445 ) 

446 

447 def get_patch_surfaces(return_set, num_cps_uvw, nurbs_dimension, element): 

448 """Get the control points positioned over the surfaces of a patch.""" 

449 

450 control_points_surface_1 = [] 

451 

452 if nurbs_dimension == 2: 

453 # As there is only one surface, it collects all the control points 

454 control_points_surface_1.extend( 

455 element.nodes[: (num_cps_uvw[0] * num_cps_uvw[1])] 

456 ) 

457 

458 # Create geometric sets for surfaces 

459 return_set["surf"] = _GeometrySetNodes( 

460 _mpy.geo.surface, nodes=control_points_surface_1 

461 ) 

462 

463 elif nurbs_dimension == 3: 

464 control_points_surface_2 = [] 

465 control_points_surface_3 = [] 

466 control_points_surface_4 = [] 

467 control_points_surface_5 = [] 

468 control_points_surface_6 = [] 

469 

470 # Surface defined on w = 0 

471 control_points_surface_1.extend( 

472 element.nodes[: (num_cps_uvw[0] * num_cps_uvw[1])] 

473 ) 

474 

475 # Surface defined on w = 1 

476 control_points_surface_2.extend( 

477 element.nodes[ 

478 (num_cps_uvw[0] * num_cps_uvw[1] * (num_cps_uvw[2] - 1)) : ( 

479 num_cps_uvw[0] * num_cps_uvw[1] * num_cps_uvw[2] 

480 ) 

481 ] 

482 ) 

483 

484 for layers_w_dir in range(num_cps_uvw[2]): 

485 # Calculate the number of control points on the w-plane 

486 num_cps_plane_w = num_cps_uvw[0] * num_cps_uvw[1] 

487 

488 for layers_u_dir in range(num_cps_uvw[0]): 

489 # Surface defined on v = 0 

490 cpgid_l1 = num_cps_uvw[0] * 0 + layers_u_dir 

491 control_points_surface_3.append( 

492 element.nodes[cpgid_l1 + num_cps_plane_w * layers_w_dir] 

493 ) 

494 

495 # Surface defined on v = 1 

496 cpgid_l3 = num_cps_uvw[0] * (num_cps_uvw[1] - 1) + layers_u_dir 

497 control_points_surface_5.append( 

498 element.nodes[cpgid_l3 + num_cps_plane_w * layers_w_dir] 

499 ) 

500 

501 for layers_v_dir in range(num_cps_uvw[1]): 

502 # Surface defined on u = 1 

503 cpgid_l2 = num_cps_uvw[0] * layers_v_dir + (num_cps_uvw[0] - 1) 

504 control_points_surface_4.append( 

505 element.nodes[cpgid_l2 + num_cps_plane_w * layers_w_dir] 

506 ) 

507 

508 # Surface defined on u = 0 

509 cpgid_l4 = num_cps_uvw[0] * layers_v_dir + 0 

510 control_points_surface_6.append( 

511 element.nodes[cpgid_l4 + num_cps_plane_w * layers_w_dir] 

512 ) 

513 

514 # Create geometric sets for surfaces 

515 return_set["surf_w_min"] = _GeometrySetNodes( 

516 _mpy.geo.surface, nodes=control_points_surface_1 

517 ) 

518 return_set["surf_w_max"] = _GeometrySetNodes( 

519 _mpy.geo.surface, nodes=control_points_surface_2 

520 ) 

521 return_set["surf_v_min"] = _GeometrySetNodes( 

522 _mpy.geo.surface, nodes=control_points_surface_3 

523 ) 

524 return_set["surf_u_max"] = _GeometrySetNodes( 

525 _mpy.geo.surface, nodes=control_points_surface_4 

526 ) 

527 return_set["surf_v_max"] = _GeometrySetNodes( 

528 _mpy.geo.surface, nodes=control_points_surface_5 

529 ) 

530 return_set["surf_u_min"] = _GeometrySetNodes( 

531 _mpy.geo.surface, nodes=control_points_surface_6 

532 ) 

533 

534 else: 

535 raise NotImplementedError( 

536 "Error, not implemented for NURBS with dimension {}!".format( 

537 nurbs_dimension 

538 ) 

539 ) 

540 

541 def get_patch_volume(return_set, num_cps_uvw, nurbs_dimension, element): 

542 """Get the control points positioned in the volume of a patch.""" 

543 

544 control_points_volume_1 = [] 

545 

546 if nurbs_dimension == 2: 

547 # As this is a surface, it's not necessary to get a volume GeometrySet 

548 pass 

549 

550 elif nurbs_dimension == 3: 

551 # As there is only one volume, it collects all the control points 

552 control_points_volume_1.extend( 

553 element.nodes[: (num_cps_uvw[0] * num_cps_uvw[1] * num_cps_uvw[2])] 

554 ) 

555 

556 # Create geometric sets for surfaces 

557 return_set["vol"] = _GeometrySetNodes( 

558 _mpy.geo.volume, nodes=control_points_volume_1 

559 ) 

560 

561 else: 

562 raise NotImplementedError( 

563 "Error, not implemented for NURBS with dimension {}".format( 

564 nurbs_dimension 

565 ) 

566 ) 

567 

568 # Create return set 

569 return_set = _GeometryName() 

570 

571 # Get the number of control points on each parametric direction that define the patch 

572 num_cps_uvw = get_num_cps_uvw(element.knot_vectors) 

573 

574 # Get the NURBS dimension 

575 nurbs_dimension = len(element.knot_vectors) 

576 

577 # Obtain the vertices of the patch 

578 get_patch_vertices(return_set, num_cps_uvw, nurbs_dimension, element) 

579 

580 # Obtain the lines of the patch 

581 get_patch_lines(return_set, num_cps_uvw, nurbs_dimension, element) 

582 

583 # Obtain the surfaces of the patch 

584 get_patch_surfaces(return_set, num_cps_uvw, nurbs_dimension, element) 

585 

586 # Obtain the volume of the patch 

587 get_patch_volume(return_set, num_cps_uvw, nurbs_dimension, element) 

588 

589 return return_set