commit 314c0620697614bef130db6da24225b087debaf6
parent fb5760b01c8aea2677cb88c8671676b5b6acf125
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 5 Oct 2022 16:42:21 +0200
Rewrite stl export for 2D geometries (allowing binary output)
Diffstat:
| M | src/scad.c | | | 121 | ++++++++++++++++++++++++++++++++++--------------------------------------------- |
1 file changed, 52 insertions(+), 69 deletions(-)
diff --git a/src/scad.c b/src/scad.c
@@ -247,7 +247,9 @@ scad_stl_export
const int binary)
{
struct str filename;
- int* tagout = NULL;
+ int* allocated_dimTags = NULL;
+ int* faces_dimTags = NULL;
+ size_t faces_dimTags_n;
int* tags = NULL;
size_t** nodeTags = NULL;
size_t* nodeTags_n = NULL;
@@ -256,9 +258,8 @@ scad_stl_export
double** pCoord = NULL;
size_t* pCoord_n = NULL;
int* dimTags = NULL;
- size_t tagoutn, i;
- int dimtag[2];
- int group;
+ size_t i, tcount;
+ int dim_ctrl;
int ierr = 0;
int* data;
size_t sz;
@@ -293,101 +294,83 @@ scad_stl_export
}
ERR(str_append(&filename, ".stl"));
- if(data[0] == 3) { /* geometry is 3D */
+ dim_ctrl = data[0];
+ if(dim_ctrl == 3) { /* geometry is 3D */
size_t dimTags_n;
- size_t tcount;
ERR(scad_synchronize());
gmshModelOccGetEntities(&dimTags, &dimTags_n, 3, &ierr);
ERR(gmsh_err_to_res_T(ierr));
- if(dimTags_n > 100000) {
- size_t dt_n;
- gmshModelOccRemoveAllDuplicates(&ierr);
- ERR(gmsh_err_to_res_T(ierr));
- gmshModelOccGetEntities(&dimTags, &dt_n, 3, &ierr);
- ERR(gmsh_err_to_res_T(ierr));
-#if 0
- if(dimTags_n != dt_n) {
- /* Entities count changed when removing duplicates !
- * Some entities are overlapping: error. */
- fprintf(stderr, "Invalid model, overlappig entities detected.\n");
- res = RES_BAD_ARG;
- goto error;
- /* TODO: implement early detection in add_xxx functions and use logger.
- * Use a non-destructive command (unlike remove duplicate).
- * (could be an option, e.g. reject_overlapping_entities, default 0) */
- }
-#endif
- }
-
- gmshModelGetBoundary(data, sz, &tagout, &tagoutn, 1, 0, 0, &ierr);
- ERR(gmsh_err_to_res_T(ierr));
- ASSERT(tagoutn % 2 == 0);
-
- /* Allocate room for arrays
- * TODO: use allocator */
- nodeTags = calloc(tagoutn/2, sizeof(*nodeTags));
- nodeTags_n = calloc(tagoutn/2, sizeof(*nodeTags_n));
- coord = calloc(tagoutn/2, sizeof(*coord));
- coord_n = calloc(tagoutn/2, sizeof(*coord_n));
- pCoord = calloc(tagoutn/2, sizeof(*pCoord));
- pCoord_n = calloc(tagoutn/2, sizeof(*pCoord_n));
- if(!nodeTags || !nodeTags_n || !coord || !coord_n || !pCoord || !pCoord_n) {
- res = RES_MEM_ERR;
- goto error;
- }
+ /* TODO: use options to set inward/outward orientation???
+ * Is it even needed???? */
for(i = 0; i < sz/2; i++) {
+ ASSERT(data[2*i] == dim_ctrl); /* Only 3D tags */
gmshModelMeshSetOutwardOrientation(data[2*i+1], &ierr);
ERR(gmsh_err_to_res_T(ierr));
}
- tcount = 0;
- for(i = 0; i < tagoutn/2; i++) {
- gmshModelMeshGetNodesByElementType(2, nodeTags+i, nodeTags_n+i,
- coord+i, coord_n+i, pCoord+i, pCoord_n+i, tagout[2*i+1], 0, &ierr);
- ERR(gmsh_err_to_res_T(ierr));
- ASSERT(coord_n[i] % 9 == 0);
- ASSERT(nodeTags_n[i] % 3 == 0);
- tcount += coord_n[i];
- }
- tcount /= 9;
- ASSERT(tcount <= UINT_MAX);
-
- ERR(write_stl(str_cget(&filename), (unsigned)tcount, coord, coord_n, binary));
+ /* Get tags to be written (boundary of geometry) */
+ gmshModelGetBoundary(data, sz, &allocated_dimTags, &faces_dimTags_n, 1, 0,
+ 0, &ierr);
+ /* Need this trick to avoid geometry->gmsh_dimTags to be freed in the 2D
+ * case */
+ faces_dimTags = allocated_dimTags;
+ ERR(gmsh_err_to_res_T(ierr));
+ ASSERT(faces_dimTags_n % 2 == 0);
} else { /* Geometry is 2D */
- FOR_EACH(i, 0, sz/2){
- ASSERT(data[2*i] == 2);
- sa_push(tags, data[2*i + 1]);
+ /* Tags to be written are the tags of the 2D object itself */
+ faces_dimTags_n = sz;
+ faces_dimTags = data;
+ for(i = 0; i < sz/2; i++) {
+ ASSERT(data[2*i] == dim_ctrl); /* Only 3D tags */
}
- group = gmshModelAddPhysicalGroup(2, tags, sz/2, -1, &ierr);
- ERR(gmsh_err_to_res_T(ierr));
+ }
- gmshWrite(str_cget(&filename), &ierr);
- ERR(gmsh_err_to_res_T(ierr));
+ /* Allocate room for arrays
+ * TODO: use allocator */
+ nodeTags = calloc(faces_dimTags_n/2, sizeof(*nodeTags));
+ nodeTags_n = calloc(faces_dimTags_n/2, sizeof(*nodeTags_n));
+ coord = calloc(faces_dimTags_n/2, sizeof(*coord));
+ coord_n = calloc(faces_dimTags_n/2, sizeof(*coord_n));
+ pCoord = calloc(faces_dimTags_n/2, sizeof(*pCoord));
+ pCoord_n = calloc(faces_dimTags_n/2, sizeof(*pCoord_n));
+ if(!nodeTags || !nodeTags_n || !coord || !coord_n || !pCoord || !pCoord_n) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
- dimtag[0]=2;
- dimtag[1]=group;
- gmshModelRemovePhysicalGroups(dimtag, 2, &ierr);
+ tcount = 0;
+ for(i = 0; i < faces_dimTags_n/2; i++) {
+ /* type = 2: 3-node triangles (see src/common/GmshDefines.h) */
+ gmshModelMeshGetNodesByElementType(2, nodeTags+i, nodeTags_n+i,
+ coord+i, coord_n+i, pCoord+i, pCoord_n+i, faces_dimTags[2*i+1], 0, &ierr);
ERR(gmsh_err_to_res_T(ierr));
+ ASSERT(nodeTags_n[i] % 3 == 0);
+ ASSERT(coord_n[i] == nodeTags_n[i] * 3);
+ tcount += coord_n[i];
}
+ tcount /= 9;
+ ASSERT(tcount <= UINT_MAX);
+
+ ERR(write_stl(str_cget(&filename), (unsigned)tcount, coord, coord_n, binary));
exit:
if(str_initialized) str_release(&filename);
- if(tagout) free(tagout);
+ if(allocated_dimTags) free(allocated_dimTags);
if(tags) sa_release(tags);
if(nodeTags) {
- for(i = 0; i < tagoutn/2; i++) free(nodeTags[i]);
+ for(i = 0; i < faces_dimTags_n/2; i++) free(nodeTags[i]);
free(nodeTags);
}
if(nodeTags_n) free(nodeTags_n);
if(coord) {
- for(i = 0; i < tagoutn/2; i++) free(coord[i]);
+ for(i = 0; i < faces_dimTags_n/2; i++) free(coord[i]);
free(coord);
}
if(coord_n) free(coord_n);
if(pCoord) {
- for(i = 0; i < tagoutn/2; i++) free(pCoord[i]);
+ for(i = 0; i < faces_dimTags_n/2; i++) free(pCoord[i]);
free(pCoord);
}
if(pCoord_n) free(pCoord_n);