From 58c2a9716684b2e9e8b4d1350493595a17c73e9e Mon Sep 17 00:00:00 2001 From: lomholy_agentic Date: Fri, 23 Oct 2026 20:36:54 +0200 Subject: [PATCH 1/4] Union mcdisplay: fix merge_lines_to_draw ownership, leaks and quadratic cost merge_lines_to_draw now appends into a geometrically grown buffer, frees lines_new->lines and leaves lines_new empty. The old version aliased lines_new->lines into an empty master (use after free in draw_circle_with_highest_priority), leaked every merged list and copied the whole master twice per merge, which is quadratic for large meshes. draw_line_with_highest_priority now always frees intersection_list.elements, and frees int_dummy (McStas) / temp_intersection (McXtrace). The McXtrace version also no longer exits when the first merged list of an empty master has no lines. Co-Authored-By: Claude Opus 5.5 --- mcstas-comps/share/union-lib.c | 65 ++++++++++++++++--------------- mcxtrace-comps/share/union-lib.c | 66 ++++++++++++++++---------------- 2 files changed, 64 insertions(+), 67 deletions(-) diff --git a/mcstas-comps/share/union-lib.c b/mcstas-comps/share/union-lib.c index 3d6b8e0c33..2aa6417664 100644 --- a/mcstas-comps/share/union-lib.c +++ b/mcstas-comps/share/union-lib.c @@ -1390,38 +1390,36 @@ void print_intersection_table(struct intersection_time_table_struct *intersectio } void merge_lines_to_draw(struct lines_to_draw *lines_master,struct lines_to_draw *lines_new) { - if (lines_master->number_of_lines == 0) { - lines_master->number_of_lines = lines_new->number_of_lines; - if (!lines_master->number_of_lines) { - return; - } - lines_master->lines = malloc(lines_master->number_of_lines*sizeof(struct line_segment)); - if (!lines_master->lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 2 - Exit!\n"); - exit(EXIT_FAILURE); - } - lines_master->lines = lines_new->lines; - // One could free lines_new->lines; - } else { - int iterate; - struct line_segment *temp_lines; - temp_lines = malloc(lines_master->number_of_lines*sizeof(struct line_segment)); - if (!temp_lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 3 - Exit!\n"); - exit(EXIT_FAILURE); - } - for (iterate = 0;iterate < lines_master->number_of_lines;iterate++) temp_lines[iterate] = lines_master->lines[iterate]; - free(lines_master->lines); - lines_master->lines = malloc((lines_master->number_of_lines+lines_new->number_of_lines)*sizeof(struct line_segment)); - if (!lines_master->lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 4 - Exit!\n"); - exit(EXIT_FAILURE); - } - for (iterate = 0;iterate < lines_master->number_of_lines;iterate++) lines_master->lines[iterate] = temp_lines[iterate]; - for (iterate = 0;iterate < lines_new->number_of_lines;iterate++) lines_master->lines[iterate+lines_master->number_of_lines] = lines_new->lines[iterate]; - lines_master->number_of_lines = lines_master->number_of_lines + lines_new->number_of_lines; - free(temp_lines); + // Appends the lines of lines_new to lines_master, then frees lines_new->lines + // and leaves lines_new empty. + // The allocation behind lines_master->lines is only ever made here, and its + // capacity is always the smallest power of two holding number_of_lines, so it + // need not be stored: appending one line at a time costs amortized O(1). + // A master is started by setting number_of_lines = 0. + int capacity, needed, iterate; + if (lines_new->number_of_lines <= 0) return; + needed = lines_master->number_of_lines + lines_new->number_of_lines; + capacity = 0; // an empty master owns no allocation (lines may be unset) + if (lines_master->number_of_lines > 0) { + capacity = 1; + while (capacity < lines_master->number_of_lines) capacity *= 2; + } + if (needed > capacity) { + int new_capacity = capacity > 0 ? capacity : 1; + struct line_segment *grown; + while (new_capacity < needed) new_capacity *= 2; + grown = realloc(capacity > 0 ? lines_master->lines : NULL, new_capacity*sizeof(struct line_segment)); + if (!grown) { + fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw - Exit!\n"); + exit(EXIT_FAILURE); + } + lines_master->lines = grown; } + for (iterate = 0;iterate < lines_new->number_of_lines;iterate++) lines_master->lines[lines_master->number_of_lines+iterate] = lines_new->lines[iterate]; + lines_master->number_of_lines = needed; + free(lines_new->lines); + lines_new->lines = NULL; + lines_new->number_of_lines = 0; } int r_has_highest_priority(Coords point,int N,struct geometry_struct **Geometries,int number_of_volumes) { @@ -1589,6 +1587,7 @@ struct lines_to_draw draw_line_with_highest_priority(Coords position1,Coords pos } } free(double_dummy); + free(int_dummy); free(temp_intersection); // Now we have a list of intersection distances between r1 and r2 and all volumes. // This list needs to be sorted before we continue! @@ -1652,9 +1651,9 @@ struct lines_to_draw draw_line_with_highest_priority(Coords position1,Coords pos draw_order.lines[draw_order.number_of_lines++] = lines[iterate]; } } - if (intersection_list.num_elements > 0) free(intersection_list.elements); } - + if (intersection_list.num_elements > 0) free(intersection_list.elements); + free(points); free(lines); free(draw_logic); diff --git a/mcxtrace-comps/share/union-lib.c b/mcxtrace-comps/share/union-lib.c index 04c4554ada..edf44fc676 100644 --- a/mcxtrace-comps/share/union-lib.c +++ b/mcxtrace-comps/share/union-lib.c @@ -1293,39 +1293,36 @@ void print_intersection_table(struct intersection_time_table_struct *intersectio } void merge_lines_to_draw(struct lines_to_draw *lines_master,struct lines_to_draw *lines_new) { - if (lines_master->number_of_lines == 0) { - lines_master->number_of_lines = lines_new->number_of_lines; - if (!lines_master->number_of_lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 1 - Exit!\n"); - exit(EXIT_FAILURE); - } - lines_master->lines = malloc(lines_master->number_of_lines*sizeof(struct line_segment)); - if (!lines_master->lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 2 - Exit!\n"); - exit(EXIT_FAILURE); - } - lines_master->lines = lines_new->lines; - // One could free lines_new->lines; - } else { - int iterate; - struct line_segment *temp_lines; - temp_lines = malloc(lines_master->number_of_lines*sizeof(struct line_segment)); - if (!temp_lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 3 - Exit!\n"); - exit(EXIT_FAILURE); - } - for (iterate = 0;iterate < lines_master->number_of_lines;iterate++) temp_lines[iterate] = lines_master->lines[iterate]; - free(lines_master->lines); - lines_master->lines = malloc((lines_master->number_of_lines+lines_new->number_of_lines)*sizeof(struct line_segment)); - if (!lines_master->lines) { - fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw 4 - Exit!\n"); - exit(EXIT_FAILURE); - } - for (iterate = 0;iterate < lines_master->number_of_lines;iterate++) lines_master->lines[iterate] = temp_lines[iterate]; - for (iterate = 0;iterate < lines_new->number_of_lines;iterate++) lines_master->lines[iterate+lines_master->number_of_lines] = lines_new->lines[iterate]; - lines_master->number_of_lines = lines_master->number_of_lines + lines_new->number_of_lines; - free(temp_lines); + // Appends the lines of lines_new to lines_master, then frees lines_new->lines + // and leaves lines_new empty. + // The allocation behind lines_master->lines is only ever made here, and its + // capacity is always the smallest power of two holding number_of_lines, so it + // need not be stored: appending one line at a time costs amortized O(1). + // A master is started by setting number_of_lines = 0. + int capacity, needed, iterate; + if (lines_new->number_of_lines <= 0) return; + needed = lines_master->number_of_lines + lines_new->number_of_lines; + capacity = 0; // an empty master owns no allocation (lines may be unset) + if (lines_master->number_of_lines > 0) { + capacity = 1; + while (capacity < lines_master->number_of_lines) capacity *= 2; + } + if (needed > capacity) { + int new_capacity = capacity > 0 ? capacity : 1; + struct line_segment *grown; + while (new_capacity < needed) new_capacity *= 2; + grown = realloc(capacity > 0 ? lines_master->lines : NULL, new_capacity*sizeof(struct line_segment)); + if (!grown) { + fprintf(stderr,"Failure allocating list in Union function merge_lines_to_draw - Exit!\n"); + exit(EXIT_FAILURE); + } + lines_master->lines = grown; } + for (iterate = 0;iterate < lines_new->number_of_lines;iterate++) lines_master->lines[lines_master->number_of_lines+iterate] = lines_new->lines[iterate]; + lines_master->number_of_lines = needed; + free(lines_new->lines); + lines_new->lines = NULL; + lines_new->number_of_lines = 0; } int r_has_highest_priority(Coords point,int N,struct geometry_struct **Geometries,int number_of_volumes) { @@ -1473,6 +1470,7 @@ struct lines_to_draw draw_line_with_highest_priority(Coords position1,Coords pos } } + free(temp_intersection); // Now we have a list of intersection distances between r1 and r2 and all volumes. // This list needs to be sorted before we continue! @@ -1534,9 +1532,9 @@ struct lines_to_draw draw_line_with_highest_priority(Coords position1,Coords pos draw_order.lines[draw_order.number_of_lines++] = lines[iterate]; } } - if (intersection_list.num_elements > 0) free(intersection_list.elements); } - + if (intersection_list.num_elements > 0) free(intersection_list.elements); + free(points); free(lines); free(draw_logic); From 015e86e640012f79cc9edf5bda3c5849f734a0ab Mon Sep 17 00:00:00 2001 From: lomholy_agentic Date: Fri, 23 Oct 2026 21:01:28 +0200 Subject: [PATCH 2/4] Union_mesh: draw BVH boxes in mcdisplay for large meshes New parameter bvh_display_layers (default 12). When the mesh BVH has more layers than this, mcdisplay draws the bounding boxes of that BVH layer (and of shallower leaves) instead of every triangle edge; 0 keeps the triangle edges. For the 871k-triangle Stanford dragon (19 layers) this is 24,891 lines instead of 1,307,274, and the mcdisplay-webgl instrument.json shrinks from 276 MB to 5.2 MB. Display only, simulation unchanged. Co-Authored-By: Claude Opus 5.5 --- mcstas-comps/share/union-lib.h | 1 + mcstas-comps/union/Union_mesh.comp | 84 +++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/mcstas-comps/share/union-lib.h b/mcstas-comps/share/union-lib.h index 7ab47e5520..9c2885d74a 100755 --- a/mcstas-comps/share/union-lib.h +++ b/mcstas-comps/share/union-lib.h @@ -522,6 +522,7 @@ int process_rot_allocated; // Keeps track of allocation status of rot_matrix_ar struct rotation_struct rotation; // Not used, is the x y and z rotation angles. int visualization_on; // If visualization_on is true, the volume will be drawn in mcdisplay, otherwise not +int mesh_display_layer; // mesh only: BVH layer whose boxes mcdisplay draws, 0 to draw the triangle edges int is_exit_volume; // If is exit volume = 1, the ray will exit the component when it enters this volume. int is_mask_volume; // 1 if volume itself is a mask (masking the ones in it's mask list), otherwise 0 int mask_index; diff --git a/mcstas-comps/union/Union_mesh.comp b/mcstas-comps/union/Union_mesh.comp index cdc3e6ca31..9a13b4df18 100644 --- a/mcstas-comps/union/Union_mesh.comp +++ b/mcstas-comps/union/Union_mesh.comp @@ -67,6 +67,7 @@ * focus_xw: [m] horiz. dimension of a rectangular area * focus_xh: [m] vert. dimension of a rectangular area * focus_r: [m] focusing on circle with this radius +* bvh_display_layers: [1] mcdisplay draws the bounding boxes of this layer of the mesh BVH (the root is layer 1) when the BVH has more layers than this, otherwise the triangle edges. Set to 0 to always draw the triangle edges. * coordinate_scale [1e-3] Multiplier that the vertex positions are multiplied by. Set to 1 for input coordinates in meters. Set to 1e-3 for input coordinates in mm. * all_surfaces: [string] Comma seperated string of Union surface definitions defined prior to this component * cut_surface: [string] Comma seperated string of Union surface definitions defined prior to this component, applied to all internal cuts @@ -100,7 +101,8 @@ SETTING PARAMETERS(string filename = 0, string mask_string=0, string mask_setting=0, number_of_activations=1, - coordinate_scale = 1e-3, string init="" + coordinate_scale = 1e-3, string init="", + int bvh_display_layers = 12 ) @@ -131,9 +133,77 @@ SHARE return 0; } + int + mesh_bvh_layers (gmesh_struct* triangle_mesh) { + // Number of layers of the BVH, the root alone is one layer + int node_stack[GMESH_BVH_STACK + 2]; + int layer_stack[GMESH_BVH_STACK + 2]; + int top = 0, layers = 0; + node_stack[0] = 0; + layer_stack[0] = 1; + top = 1; + while (top > 0) { + top--; + gmesh_node* node = &triangle_mesh->node[node_stack[top]]; + int layer = layer_stack[top]; + if (layer > layers) + layers = layer; + if (node->count == 0) { + node_stack[top] = node->first; + layer_stack[top++] = layer + 1; + node_stack[top] = node->first + 1; + layer_stack[top++] = layer + 1; + } + } + return layers; + } + + void + mcdisplay_mesh_bvh_boxes (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { + // Draws the bounding box of every BVH node in layer mesh_display_layer, and of the leaves above it, + // in the frame of the master component + struct geometry_struct* geometry = Geometries[index]; + gmesh_struct* triangle_mesh = geometry->geometry_parameters.p_mesh; + int node_stack[GMESH_BVH_STACK + 2]; + int layer_stack[GMESH_BVH_STACK + 2]; + // corner bits (x, y, z) of the 12 box edges + const int box_edges[12][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, { 0, 2 }, { 1, 3 }, { 4, 6 }, { 5, 7 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } }; + int top = 1; + int corner, edge; + struct lines_to_draw lines_to_draw_temp; + node_stack[0] = 0; + layer_stack[0] = 1; + while (top > 0) { + top--; + gmesh_node* node = &triangle_mesh->node[node_stack[top]]; + int layer = layer_stack[top]; + if (node->count == 0 && layer < geometry->mesh_display_layer) { + node_stack[top] = node->first; + layer_stack[top++] = layer + 1; + node_stack[top] = node->first + 1; + layer_stack[top++] = layer + 1; + continue; + } + Coords corners[8]; + for (corner = 0; corner < 8; corner++) { + Coords local = coords_set ((corner & 1) ? node->hi.x : node->lo.x, (corner & 2) ? node->hi.y : node->lo.y, (corner & 4) ? node->hi.z : node->lo.z); + corners[corner] = coords_add (rot_apply (geometry->rotation_matrix, local), geometry->center); + } + for (edge = 0; edge < 12; edge++) { + lines_to_draw_temp = draw_line_with_highest_priority (corners[box_edges[edge][0]], corners[box_edges[edge][1]], index, Geometries, number_of_volumes, 100); + merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); + } + } + } + void mcdisplay_mesh_function (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { - // Draws each edge of the polygons in the file once, in the frame of the master component + // Draws each edge of the polygons in the file once, in the frame of the master component, + // or the BVH boxes of layer mesh_display_layer when that is set + if (Geometries[index]->mesh_display_layer > 0) { + mcdisplay_mesh_bvh_boxes (lines_to_draw_output, index, Geometries, number_of_volumes); + return; + } gmesh_struct* triangle_mesh = Geometries[index]->geometry_parameters.p_mesh; struct pointer_to_1d_coords_list points_struct = Geometries[index]->shell_points (Geometries[index], 1); Coords* points = points_struct.elements; @@ -400,6 +470,16 @@ INITIALIZE mesh_vol.geometry.eShape = mesh; mesh_vol.geometry.priority_value = priority; mesh_vol.geometry.visualization_on = visualize; + mesh_vol.geometry.mesh_display_layer = 0; + if (bvh_display_layers > 0) { + int layers = mesh_bvh_layers (&mesh_data); + if (layers > bvh_display_layers) { + mesh_vol.geometry.mesh_display_layer = bvh_display_layers; + if (mcdotrace) + MPI_MASTER (printf ("Union_mesh %s: mcdisplay draws the BVH boxes of layer %d of %d instead of the %d triangles\n", NAME_CURRENT_COMP, + bvh_display_layers, layers, mesh_data.ntris);) + } + } mesh_vol.geometry.geometry_p_interact = p_interact; mesh_vol.geometry.within_function = &r_within_mesh; mesh_vol.geometry.geometry_parameters.p_mesh = &mesh_data; From 12058c49729b8de3d89da34dd00b9e2ffc0fa36b Mon Sep 17 00:00:00 2001 From: lomholy_agentic Date: Sat, 24 Oct 2026 12:09:08 +0200 Subject: [PATCH 3/4] Union_mesh: keep the mcdisplay BVH layer in a mesh_storage struct The mesh geometry parameters are now a struct mesh_storage, holding the geometry-mesh-lib gmesh_struct and the BVH display layer, like the box/cylinder/sphere/cone storage structs. geometry_parameters.p_mesh becomes p_mesh_storage, and mesh_display_layer is removed from geometry_struct. No change in behaviour. Co-Authored-By: Claude Opus 5.5 --- mcstas-comps/share/union-lib.c | 16 +++++++------- mcstas-comps/share/union-lib.h | 8 +++++-- mcstas-comps/union/Union_mesh.comp | 34 +++++++++++++++--------------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/mcstas-comps/share/union-lib.c b/mcstas-comps/share/union-lib.c index 2aa6417664..2f1c55346d 100644 --- a/mcstas-comps/share/union-lib.c +++ b/mcstas-comps/share/union-lib.c @@ -1804,14 +1804,14 @@ union geometry_parameter_union allocate_cone_storage_copy(union geometry_paramet union geometry_parameter_union allocate_mesh_copy(union geometry_parameter_union *union_input) { union geometry_parameter_union union_output; - // Allocate the space for a gmesh_struct in the new union_output (union as the c structre) - union_output.p_mesh = malloc(sizeof(gmesh_struct)); - if (!union_output.p_mesh) { + // Allocate the space for a mesh_storage in the new union_output (union as the c structre) + union_output.p_mesh_storage = malloc(sizeof(struct mesh_storage)); + if (!union_output.p_mesh_storage) { fprintf(stderr,"Failure allocating list in Union function allocate_mesh_copy - Exit!\n"); exit(EXIT_FAILURE); } // Copy the input storage to the output - *union_output.p_mesh = *union_input->p_mesh; + *union_output.p_mesh_storage = *union_input->p_mesh_storage; return union_output; } @@ -2759,7 +2759,7 @@ This function was created by Martin Olsen at NBI on september 20, 2018. int r_within_mesh(Coords pos,struct geometry_struct *geometry) { // Point in mesh test (parity of ray crossings) in the frame of the mesh component Coords local_position = rot_apply(geometry->transpose_rotation_matrix, coords_sub(pos, geometry->center)); - return gmesh_inside(geometry->geometry_parameters.p_mesh, local_position); + return gmesh_inside(&geometry->geometry_parameters.p_mesh_storage->mesh, local_position); } int sample_mesh_intersect(double *t, @@ -2770,7 +2770,7 @@ int sample_mesh_intersect(double *t, // Times of intersection with a mesh component, nearest first, with the unit // outward normals rotated back to the frame of the master component. // Hits slightly before r are kept, so that the surface the ray leaves is found. - gmesh_struct *triangle_mesh = geometry->geometry_parameters.p_mesh; + gmesh_struct *triangle_mesh = &geometry->geometry_parameters.p_mesh_storage->mesh; gmesh_hit hits[GMESH_MAX_HITS]; Coords position = rot_apply(geometry->transpose_rotation_matrix, coords_sub(coords_set(r[0], r[1], r[2]), geometry->center)); Coords velocity = rot_apply(geometry->transpose_rotation_matrix, coords_set(v[0], v[1], v[2])); @@ -4162,7 +4162,7 @@ int mesh_overlaps_mesh(struct geometry_struct *geometry1,struct geometry_struct } // Secondary check with edges intersecting on faces if (geometry1->eShape==mesh){ - gmesh_struct *mesh1 = geometry1->geometry_parameters.p_mesh; + gmesh_struct *mesh1 = &geometry1->geometry_parameters.p_mesh_storage->mesh; Coords vert1, vert2, vert3; for (i = 0; i < mesh1->ntris; i++){ vert1 = shell_points1.elements[mesh1->tri[3*i]]; @@ -4186,7 +4186,7 @@ int mesh_overlaps_mesh(struct geometry_struct *geometry1,struct geometry_struct } } if (geometry2->eShape==mesh){ - gmesh_struct *mesh2 = geometry2->geometry_parameters.p_mesh; + gmesh_struct *mesh2 = &geometry2->geometry_parameters.p_mesh_storage->mesh; Coords vert1, vert2, vert3; for (i = 0; i < mesh2->ntris; i++){ vert1 = shell_points2.elements[mesh2->tri[3*i]]; diff --git a/mcstas-comps/share/union-lib.h b/mcstas-comps/share/union-lib.h index 9c2885d74a..d0d298e17b 100755 --- a/mcstas-comps/share/union-lib.h +++ b/mcstas-comps/share/union-lib.h @@ -225,7 +225,7 @@ union geometry_parameter_union{ struct cylinder_storage *p_cylinder_storage; struct box_storage *p_box_storage; struct cone_storage *p_cone_storage; - gmesh_struct *p_mesh; + struct mesh_storage *p_mesh_storage; // add as many pointers to structs as wanted, without increasing memory footprint. }; @@ -522,7 +522,6 @@ int process_rot_allocated; // Keeps track of allocation status of rot_matrix_ar struct rotation_struct rotation; // Not used, is the x y and z rotation angles. int visualization_on; // If visualization_on is true, the volume will be drawn in mcdisplay, otherwise not -int mesh_display_layer; // mesh only: BVH layer whose boxes mcdisplay draws, 0 to draw the triangle edges int is_exit_volume; // If is exit volume = 1, the ray will exit the component when it enters this volume. int is_mask_volume; // 1 if volume itself is a mask (masking the ones in it's mask list), otherwise 0 int mask_index; @@ -1075,6 +1074,11 @@ double height; Coords direction_vector; }; +struct mesh_storage{ +gmesh_struct mesh; // triangle mesh and BVH, in the frame of the mesh component +int display_layer; // BVH layer whose boxes mcdisplay draws, 0 to draw the triangle edges +}; + // A number of functions below use Dot() as scalar product, replace by coords_sp define #define Dot(a, b) coords_sp(a, b) diff --git a/mcstas-comps/union/Union_mesh.comp b/mcstas-comps/union/Union_mesh.comp index 9a13b4df18..aff80d5ad2 100644 --- a/mcstas-comps/union/Union_mesh.comp +++ b/mcstas-comps/union/Union_mesh.comp @@ -160,10 +160,10 @@ SHARE void mcdisplay_mesh_bvh_boxes (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { - // Draws the bounding box of every BVH node in layer mesh_display_layer, and of the leaves above it, + // Draws the bounding box of every BVH node in the display layer of the mesh storage, and of the leaves above it, // in the frame of the master component struct geometry_struct* geometry = Geometries[index]; - gmesh_struct* triangle_mesh = geometry->geometry_parameters.p_mesh; + gmesh_struct* triangle_mesh = &geometry->geometry_parameters.p_mesh_storage->mesh; int node_stack[GMESH_BVH_STACK + 2]; int layer_stack[GMESH_BVH_STACK + 2]; // corner bits (x, y, z) of the 12 box edges @@ -177,7 +177,7 @@ SHARE top--; gmesh_node* node = &triangle_mesh->node[node_stack[top]]; int layer = layer_stack[top]; - if (node->count == 0 && layer < geometry->mesh_display_layer) { + if (node->count == 0 && layer < geometry->geometry_parameters.p_mesh_storage->display_layer) { node_stack[top] = node->first; layer_stack[top++] = layer + 1; node_stack[top] = node->first + 1; @@ -199,12 +199,12 @@ SHARE void mcdisplay_mesh_function (struct lines_to_draw* lines_to_draw_output, int index, struct geometry_struct** Geometries, int number_of_volumes) { // Draws each edge of the polygons in the file once, in the frame of the master component, - // or the BVH boxes of layer mesh_display_layer when that is set - if (Geometries[index]->mesh_display_layer > 0) { + // or the BVH boxes of the display layer when that is set + if (Geometries[index]->geometry_parameters.p_mesh_storage->display_layer > 0) { mcdisplay_mesh_bvh_boxes (lines_to_draw_output, index, Geometries, number_of_volumes); return; } - gmesh_struct* triangle_mesh = Geometries[index]->geometry_parameters.p_mesh; + gmesh_struct* triangle_mesh = &Geometries[index]->geometry_parameters.p_mesh_storage->mesh; struct pointer_to_1d_coords_list points_struct = Geometries[index]->shell_points (Geometries[index], 1); Coords* points = points_struct.elements; long* edges = malloc (2 * triangle_mesh->faceSize * sizeof (long)); @@ -243,7 +243,7 @@ SHARE struct pointer_to_1d_coords_list allocate_shell_points (struct geometry_struct* geometry, int max_number_of_points) { // Function that returns all vertex points in the frame of the master component - gmesh_struct* triangle_mesh = geometry->geometry_parameters.p_mesh; + gmesh_struct* triangle_mesh = &geometry->geometry_parameters.p_mesh_storage->mesh; struct pointer_to_1d_coords_list mesh_shell_array; mesh_shell_array.elements = malloc (triangle_mesh->nverts * sizeof (Coords)); @@ -284,7 +284,7 @@ DECLARE struct Volume_struct mesh_vol; // Mesh storage contains the triangle mesh read with geometry-mesh-lib - gmesh_struct mesh_data; + struct mesh_storage this_mesh_storage; // Structs for surface effects struct surface_stack_struct surface_stack; @@ -439,19 +439,19 @@ INITIALIZE // READ FILE //============================================================================== // Read the STL/OFF/PLY file in the frame of this component, scaled by coordinate_scale - if (!gmesh_init (filename, coordinate_scale, GMESH_PROPS_IGNORE, &mesh_data)) { + if (!gmesh_init (filename, coordinate_scale, GMESH_PROPS_IGNORE, &this_mesh_storage.mesh)) { printf ("\nERROR IN %s: could not read the geometry file %s\n", NAME_CURRENT_COMP, filename); exit (1); } - if (!mesh_data.closed) { + if (!this_mesh_storage.mesh.closed) { printf ("\n\nERROR: Input mesh %s of %s is not closed: %d boundary and %d non-manifold edges." "\nUnion_mesh requires a closed (watertight) mesh.\n\n", - filename, NAME_CURRENT_COMP, mesh_data.nboundary, mesh_data.nnonmanifold); + filename, NAME_CURRENT_COMP, this_mesh_storage.mesh.nboundary, this_mesh_storage.mesh.nnonmanifold); exit (1); } // surface_index of a mesh hit is the triangle index, all triangles share one surface stack - mesh_vol.geometry.number_of_faces = mesh_data.ntris; + mesh_vol.geometry.number_of_faces = this_mesh_storage.mesh.ntris; mesh_vol.geometry.surface_stack_for_each_face = malloc (mesh_vol.geometry.number_of_faces * sizeof (struct surface_stack_struct*)); if (!mesh_vol.geometry.surface_stack_for_each_face) { printf ("\nERROR IN %s: could not allocate surface stacks\n", NAME_CURRENT_COMP); @@ -470,19 +470,19 @@ INITIALIZE mesh_vol.geometry.eShape = mesh; mesh_vol.geometry.priority_value = priority; mesh_vol.geometry.visualization_on = visualize; - mesh_vol.geometry.mesh_display_layer = 0; + this_mesh_storage.display_layer = 0; if (bvh_display_layers > 0) { - int layers = mesh_bvh_layers (&mesh_data); + int layers = mesh_bvh_layers (&this_mesh_storage.mesh); if (layers > bvh_display_layers) { - mesh_vol.geometry.mesh_display_layer = bvh_display_layers; + this_mesh_storage.display_layer = bvh_display_layers; if (mcdotrace) MPI_MASTER (printf ("Union_mesh %s: mcdisplay draws the BVH boxes of layer %d of %d instead of the %d triangles\n", NAME_CURRENT_COMP, - bvh_display_layers, layers, mesh_data.ntris);) + bvh_display_layers, layers, this_mesh_storage.mesh.ntris);) } } mesh_vol.geometry.geometry_p_interact = p_interact; mesh_vol.geometry.within_function = &r_within_mesh; - mesh_vol.geometry.geometry_parameters.p_mesh = &mesh_data; + mesh_vol.geometry.geometry_parameters.p_mesh_storage = &this_mesh_storage; mesh_vol.geometry.intersect_function = &sample_mesh_intersect; mesh_vol.geometry.mcdisplay_function = &mcdisplay_mesh_function; mesh_vol.geometry.shell_points = &allocate_shell_points; From 1fb7781944aea379c9c3750944214281f8eedf2f Mon Sep 17 00:00:00 2001 From: Diablo Date: Wed, 28 Oct 2026 12:13:59 +0100 Subject: [PATCH 4/4] Apply clangformat to union mesh component --- mcstas-comps/union/Union_mesh.comp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mcstas-comps/union/Union_mesh.comp b/mcstas-comps/union/Union_mesh.comp index aff80d5ad2..903150111a 100644 --- a/mcstas-comps/union/Union_mesh.comp +++ b/mcstas-comps/union/Union_mesh.comp @@ -190,7 +190,8 @@ SHARE corners[corner] = coords_add (rot_apply (geometry->rotation_matrix, local), geometry->center); } for (edge = 0; edge < 12; edge++) { - lines_to_draw_temp = draw_line_with_highest_priority (corners[box_edges[edge][0]], corners[box_edges[edge][1]], index, Geometries, number_of_volumes, 100); + lines_to_draw_temp + = draw_line_with_highest_priority (corners[box_edges[edge][0]], corners[box_edges[edge][1]], index, Geometries, number_of_volumes, 100); merge_lines_to_draw (lines_to_draw_output, &lines_to_draw_temp); } } @@ -476,8 +477,8 @@ INITIALIZE if (layers > bvh_display_layers) { this_mesh_storage.display_layer = bvh_display_layers; if (mcdotrace) - MPI_MASTER (printf ("Union_mesh %s: mcdisplay draws the BVH boxes of layer %d of %d instead of the %d triangles\n", NAME_CURRENT_COMP, - bvh_display_layers, layers, this_mesh_storage.mesh.ntris);) + MPI_MASTER (printf ("Union_mesh %s: mcdisplay draws the BVH boxes of layer %d of %d instead of the %d triangles\n", NAME_CURRENT_COMP, bvh_display_layers, + layers, this_mesh_storage.mesh.ntris);) } } mesh_vol.geometry.geometry_p_interact = p_interact;