star-cad

Geometric operators for computer-aided design
git clone git://git.meso-star.fr/star-cad.git
Log | Files | Refs | README | LICENSE

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:
Msrc/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);