The vis_MapMeshSetPatchParami function is used to specify that a 8 by 2 grid of quadrilateral elements is to be generated. The vis_MapMeshSetParami function is used to specify parabolic elements. The nodes and finite elements are actually generated by calling vis_MapMeshGenerate. The generated nodes and elements are entered into the Connect object which is passed in the argument list. Lastly, the generated nodes and elements are printed.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[4][3] = { {0.,0.,0.}, {10.,0.,0.}, {10.,1.,0.}, {0.,1.,0.} }; /*---------------------------------------------------------------------- Generate a Surface Mapped Mesh ----------------------------------------------------------------------*/ int main() { vis_MapMesh *mapmesh; vis_Connect *connect; Vint i; Vint pix[4]; Vint numnp, numel; Vdouble x[3]; Vint aid, aid1; Vint nix, ix[8]; /* create MapMesh object */ mapmesh = vis_MapMeshBegin (); vis_MapMeshDef (mapmesh,4,1); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < 4; i++) { vis_MapMeshSetPoint (mapmesh,i+1,coords[i]); } /* define patch connectivity */ pix[0] = 1; pix[1] = 2; pix[2] = 3; pix[3] = 4; vis_MapMeshSetPatch (mapmesh,1,VIS_SHAPEQUAD,2,0,0,pix); /* set assoc of 100 at edge 4 */ vis_MapMeshSetPatchAssoc (mapmesh,VIS_MISCID,1,SYS_EDGE,4,100); /* set assoc of 200 at point 2 */ vis_MapMeshSetPointAssoc (mapmesh,VIS_MISCID1,2,200); /* set mesh parameters */ vis_MapMeshSetParami (mapmesh,VIS_MESH_MAXI,3); vis_MapMeshSetPatchParami (mapmesh,1,VIS_MESH_SHAPE,VIS_SHAPEQUAD); vis_MapMeshSetPatchParami (mapmesh,1,MAPMESH_NUMELEMI,8); vis_MapMeshSetPatchParami (mapmesh,1,MAPMESH_NUMELEMJ,2); /* generate */ vis_MapMeshGenerate (mapmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5],ix[6],ix[7]); } /* end objects */ vis_ConnectEnd (connect); vis_MapMeshEnd (mapmesh); return 0; }
#include <stdio.h> #include <math.h> #include "base/base.h" #include "vis/vismesh.h" /*---------------------------------------------------------------------- Generate a Multiple Patch Mapped Mesh ----------------------------------------------------------------------*/ int main() { vis_MapMesh *mapmesh; vis_Connect *connect; Vdouble radius, angle, length, span, radian; Vdouble coords[10][3]; Vint i; Vint pix[8]; Vint numnp, numel; Vdouble x[3]; Vint aid, aid1, pid; Vint nix, ix[4]; radius = 3.; angle = 60.; length = 10.; span = 50.; /* create MapMesh object */ mapmesh = vis_MapMeshBegin (); vis_MapMeshDef (mapmesh,10,2); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectDef (connect,0,0); /* compute points */ /* cross section radius, compute 4 points */ for(i = 0; i < 4; i++) { radian = i*angle/3. * (3.14159/180.); coords[i][0] = radius - radius*cos(radian); coords[i][1] = radius*sin(radian); coords[i][2] = 0.; } /* cross section straight length, 1 additional point */ coords[4][0] = coords[3][0] + length*sin(radian); coords[4][1] = coords[3][1] + length*cos(radian); coords[4][2] = 0.; /* span, 5 more points offset in z from first 5 points */ for(i = 0; i < 5; i++) { coords[i+5][0] = coords[i][0]; coords[i+5][1] = coords[i][1]; coords[i+5][2] = coords[i][2] + span; } /* define points */ for (i = 0; i < 10; i++) { vis_MapMeshSetPoint (mapmesh,i+1,coords[i]); } /* define patch point connectivity */ /* patch 1 */ pix[0] = 1; pix[1] = 2; pix[2] = 3; pix[3] = 4; pix[4] = 6; pix[5] = 7; pix[6] = 8; pix[7] = 9; vis_MapMeshSetPatch (mapmesh,1,VIS_SHAPEQUAD,4,2,0,pix); /* patch 2 */ pix[0] = 4; pix[1] = 5; pix[2] = 9; pix[3] = 10; vis_MapMeshSetPatch (mapmesh,2,VIS_SHAPEQUAD,2,2,0,pix); /* set assoc of 1 at z=0. edge */ vis_MapMeshSetPatchAssoc (mapmesh,VIS_MISCID,1,SYS_EDGE,1,1); vis_MapMeshSetPatchAssoc (mapmesh,VIS_MISCID,2,SYS_EDGE,1,1); /* set assoc of 2 at z=span edge */ vis_MapMeshSetPatchAssoc (mapmesh,VIS_MISCID,1,SYS_EDGE,3,2); vis_MapMeshSetPatchAssoc (mapmesh,VIS_MISCID,2,SYS_EDGE,3,2); /* set property ids as element associations */ vis_MapMeshSetPatchAssoc (mapmesh,VIS_PROPID,1,SYS_ELEM,0,10); vis_MapMeshSetPatchAssoc (mapmesh,VIS_PROPID,2,SYS_ELEM,0,20); /* set mesh parameters */ vis_MapMeshSetParami (mapmesh,VIS_MESH_MAXI,2); /* patch 1 */ vis_MapMeshSetPatchParami (mapmesh,1,VIS_MESH_SHAPE,VIS_SHAPEQUAD); vis_MapMeshSetPatchParami (mapmesh,1,MAPMESH_NUMELEMI,4); vis_MapMeshSetPatchParami (mapmesh,1,MAPMESH_NUMELEMJ,20); /* patch 2 */ vis_MapMeshSetPatchParami (mapmesh,2,VIS_MESH_SHAPE,VIS_SHAPEQUAD); vis_MapMeshSetPatchParami (mapmesh,2,MAPMESH_NUMELEMI,10); vis_MapMeshSetPatchParami (mapmesh,2,MAPMESH_NUMELEMJ,20); /* generate */ vis_MapMeshGenerate (mapmesh,connect); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam41a.bdf"); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); vis_ConnectElemAssoc (connect,VIS_PROPID,1,&i,&pid); printf("id= %d ix= %d %d %d %d, pid= %d\n", i,ix[0],ix[1],ix[2],ix[3],pid); } /* end objects */ vis_ConnectEnd (connect); vis_MapMeshEnd (mapmesh); return 0; }
The cross section geometry is input as 9 nodes in the x-z global coordinate plane connected by 2 parabolic triangular elements. The node coordinates are defined using vis_ExtMeshSetNode and are always expressed in the global coordinate system. A CoordSys object is used to define a cylindrical coordinate system in which the points defining the extrusion path are defined. The two path endpoints are defined using vis_ExtMeshSetPoint. The point coordinates are entered in the cylindrical coordinate system.
The vis_ExtMeshSetPathParami function is used to specify that 4 planes of elements are to be extruded. Since the cross section contains 2 elements, the total number of elements generated will be 8. The function vis_ExtMeshGenerate generates the nodes and elements. During the mesh generation process, the input node coordinates are transformed to the cylindrical coordinate system defined by CoordSys. All nodes are then extruded along the specified path in the cylindrical coordinate system. The generated nodes are then transformed back to the global coordinate system before they are entered into the Connect object which is passed in the argument list. Lastly, the generated nodes and elements are printed.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble xnode[9][3] = { {2.,0.,0.}, {3.,0.,0.}, {4.,0.,0.}, {2.,0.,1.}, {3.,0.,1.}, {4.,0.,1.}, {2.,0.,2.}, {3.,0.,2.}, {4.,0.,2.} }; static Vint ixtri[2][6] = { {1, 3, 7, 2, 5, 4}, {3, 9, 7, 6, 8, 5} }; static Vdouble origin[3] = {0.,0.,0.}; static Vdouble triad[3][3] = {{1.,0.,0.},{0.,1.,0.},{0.,0.,1.}}; /*---------------------------------------------------------------------- Generate an Extruded Mesh ----------------------------------------------------------------------*/ int main() { vis_ExtMesh *extmesh; vis_Connect *connect; Vint i; Vdouble xp[3]; Vint pix[2]; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[15]; /* create ExtMesh object */ extmesh = vis_ExtMeshBegin (); vis_ExtMeshDef (extmesh,9,2); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectDef (connect,0,0); /* set coordinate system transformation */ vis_ExtMeshSetOriginTriad (extmesh,SYS_CYLINDRICAL,origin,triad); /* define nodes */ for (i = 0; i < 9; i++) { vis_ExtMeshSetNode (extmesh,i+1,xnode[i]); } /* define parabolic triangle connectivity */ for (i = 0; i < 2; i++) { vis_ExtMeshSetElem (extmesh,i+1,VIS_SHAPETRI,3,0,ixtri[i]); } /* define path end points */ xp[0] = 0.; xp[1] = 0.; xp[2] = 0.; vis_ExtMeshSetPoint (extmesh,1,xp); xp[1] = 45.; vis_ExtMeshSetPoint (extmesh,2,xp); pix[0] = 1; pix[1] = 2; vis_ExtMeshSetPath (extmesh,2,pix); /* set mesh parameters */ vis_ExtMeshSetPathParami (extmesh,1,VIS_MESH_NUMELEMENTS,4); /* generate */ vis_ExtMeshGenerate (extmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %e, y= %e, z= %e\n",i,x[0],x[1],x[2]); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); printf(" %d %d %d %d %d %d\n", ix[6],ix[7],ix[8],ix[9],ix[10],ix[11]); printf(" %d %d %d\n", ix[12],ix[13],ix[14]); } /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam42.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_ExtMeshEnd (extmesh); return 0; }
The vis_ExtMeshSetParami function is used to activate extrusion along node normals, specify the number of layers (4), flag the fact that the normals are in the opposite direction to the triangle connectivity sense and enable the assignment of the VIS_GEOFACE association to the element faces and nodes generated on the initial and final faces of the extruded mesh. Since the normals are opposite to the connectivity sense, the connectivity of the resulting wedge elements must be reversed to yield a positive volume.
The function vis_ExtMeshGenerate generates the nodes and elements. Lastly, the generated nodes and elements are printed.
#include <math.h> #include "base/base.h" #include "vis/vismesh.h" /* a simple 5 sided unit cube */ static Vdouble xc[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; /* extrusion directions for each node */ /* these will be scaled to desired boundary layer thickness */ static Vdouble vn[8][3] = { {1.,1.,1.}, {-1.,1.,1.}, {1.,-1.,1.}, {-1.,-1.,1.}, {1.,1.,0.}, {-1.,1.,0.}, {1.,-1.,0.}, {-1.,-1.,0.} }; static Vint tris[10][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3} }; /*---------------------------------------------------------------------- Generate an Extruded Mesh along Normals ----------------------------------------------------------------------*/ int main() { Vint i, j; vis_ExtMesh *extmesh; vis_Connect *connect; Vdouble mag, layersize; Vdouble normal[8][3]; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[6], aid; /* perform extrusion meshing */ /* set normal length to layer size of 0.25 */ layersize = .25; for(i = 0; i < 8; ++i) { mag = sqrt(vn[i][0]*vn[i][0]+vn[i][1]*vn[i][1]+vn[i][2]*vn[i][2]); mag = layersize/mag; normal[i][0] = mag*vn[i][0]; normal[i][1] = mag*vn[i][1]; normal[i][2] = mag*vn[i][2]; } /* create ExtMesh object */ extmesh = vis_ExtMeshBegin(); /* 8 input nodes, 10 input triangles */ vis_ExtMeshDef (extmesh,8,10); /* enter starting surface and normals */ for(i = 1; i <= 8; ++i) { vis_ExtMeshSetNode (extmesh,i,xc[i-1]); vis_ExtMeshSetNodeNormal (extmesh,i,normal[i-1]); } for(i = 1; i <= 10; ++i) { vis_ExtMeshSetElem (extmesh,i,SYS_SHAPETRI,2,0,tris[i-1]); } /* set mesh parameters */ vis_ExtMeshSetParami (extmesh,EXTMESH_NORMAL,SYS_ON); vis_ExtMeshSetParamd (extmesh,VIS_MESH_GROWTHRATE,2.); vis_ExtMeshSetParami (extmesh,EXTMESH_LOCALRECEDE,SYS_ON); vis_ExtMeshSetNormalPath (extmesh,4,1.,SYS_OFF); /* the normals are pointing in the opposite direction to the connectivity sense of the surface triangles */ vis_ExtMeshSetParami (extmesh,EXTMESH_REVERSE,SYS_ON); /* mark faces on original layer with value of 1 and faces on final layer with value of 2 */ vis_ExtMeshSetParami (extmesh,EXTMESH_FACEMARK,VIS_GEOFACE); /* create Connect object and generate */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); vis_ExtMeshGenerate (extmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %e, y= %e, z= %e\n",i,x[0],x[1],x[2]); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); for(j = 1; j <= 5; j++) { vis_ConnectElemEntAssoc (connect,VIS_GEOFACE,SYS_FACE,i,j,&aid); if(aid == 1) { printf("element face= %d on original face\n",j); } else if(aid == 2) { printf("element face= %d on final face\n",j); } } } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam42a.bdf"); vis_ConnectEnd (connect); vis_ExtMeshEnd (extmesh); return 0; }
A simple unit cube defined by 12 boundary triangles defines the surface geometry. These triangles are entered into the SurfMesh object for generating the initial surface mesh of triangles. The resulting triangles are entered into the ExtMesh object. The normals of the surface triangle mesh are averaged at each node and scaled by the desired boundary layer length of .25. Since the boundary layer mesh is extruded in the opposite direction of the sense of the boundary triangle connectivity, the parameter EXTMESH_REVERSE is set to create positive volume boundary layer elements. The extrusion distance is large enough that the node vectors begin to "intersect" resulting in inverted elements. The parameter EXTMESH_LOCALCHECK is enabled to check for inversion and recede the extrusion distance sufficiently to avoid inversion. The parameter EXTMESH_FACEMARK is enabled to mark all nodes and element face on the final extrusion layer with the association VIS_GEOFACE. All nodes and element faces on the initial extrusion layer are marked with a value of 1 and with a 2 on the final extrusion layer. This will facilitate passing the triangles on the final extrusion layer to the TetMesh module for the final tetrahedral meshing of the interior.
Finally, using the VIS_GEOFACE association, the nodes and triangles on the final extrusion layer are detected and passed to the TetMesh module. The VIS_MESH_INWARD parameter must be set since the sense of the triangle on the final extrusion layer will point to the inside of the geometry.
#include <stdio.h> #include <math.h> #include "base/base.h" #include "vis/vismesh.h" /* a simple unit cube */ static Vdouble xc[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint tefl[12][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; /* surface triangle node normals */ static Vdouble norms[12][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Cross product between two vectors ----------------------------------------------------------------------*/ static void cross(Vdouble a[3], Vdouble b[3], Vdouble c[3]) { c[0] = a[1]*b[2]-a[2]*b[1]; c[1] = a[2]*b[0]-a[0]*b[2]; c[2] = a[0]*b[1]-a[1]*b[0]; } /*---------------------------------------------------------------------- Difference between two vectors ----------------------------------------------------------------------*/ static void diff(Vdouble a[3], Vdouble b[3], Vdouble c[3]) { c[0] = a[0]-b[0]; c[1] = a[1]-b[1]; c[2] = a[2]-b[2]; } /*---------------------------------------------------------------------- Generate Extruded Boundary Layer with Interior TetMesh ----------------------------------------------------------------------*/ int main() { vis_IdTran *idtran; vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_ExtMesh *extmesh; vis_Connect *connectsurf, *connectext, *connecttet, *connectall; vis_Group *ngroup, *fgroup; Vdouble (*normal)[3], x[3][3], u[3], v[3], w[3], mag; Vint i, j, nix, ix[10], numnpsurf, numelsurf, numnpext, numelext; Vint jx[3], numnp, numel, no, aid, num; /* perform surface meshing */ /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,8,12); /* define points */ for (i = 0; i < 8; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 12; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); } /* set mesh parameters */ vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,0.2); vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam42b_srf.bdf"); /* perform extrusion meshing */ /* compute averaged nodal normals */ vis_ConnectNumber (connectsurf,SYS_ELEM,&numelsurf); vis_ConnectNumber (connectsurf,SYS_NODE,&numnpsurf); normal = (Vdouble(*)[3])malloc(3*numnpsurf*sizeof(Vdouble)); for(i = 0; i < numnpsurf; ++i) { normal[i][0] = normal[i][1] = normal[i][2] = 0.; } for(i = 0; i < numelsurf; ++i) { vis_ConnectElemNode (connectsurf,i+1,&nix,ix); vis_ConnectCoordsdv (connectsurf,nix,ix,x); diff(x[1],x[0],u); diff(x[2],x[0],v); cross(u,v,w); mag = sqrt(w[0]*w[0]+w[1]*w[1]+w[2]*w[2]); w[0] /= mag; w[1] /= mag; w[2] /= mag; for(j = 0; j < 3; ++j) { normal[ix[j]-1][0] += w[0]; normal[ix[j]-1][1] += w[1]; normal[ix[j]-1][2] += w[2]; } } /* set normal length to layer size of 0.25 */ for(i = 0; i < numnpsurf; ++i) { mag = sqrt(normal[i][0]*normal[i][0]+ normal[i][1]*normal[i][1]+ normal[i][2]*normal[i][2]); mag = 0.25/mag; normal[i][0] *= -mag; normal[i][1] *= -mag; normal[i][2] *= -mag; } /* create ExtMesh object */ extmesh = vis_ExtMeshBegin(); vis_ExtMeshDef (extmesh,numnpsurf,numelsurf); /* enter generated surface mesh */ for(i = 1; i <= numnpsurf; ++i) { vis_ConnectCoordsdv (connectsurf,1,&i,&u); vis_ExtMeshSetNode (extmesh,i,u); vis_ExtMeshSetNodeNormal (extmesh,i,normal[i-1]); } for(i = 1; i <= numelsurf; ++i) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_ExtMeshSetElem (extmesh,i,SYS_SHAPETRI,2,0,ix); } /* set mesh parameters */ vis_ExtMeshSetParami (extmesh,EXTMESH_NORMAL,SYS_ON); vis_ExtMeshSetParamd (extmesh,VIS_MESH_GROWTHRATE,2.); vis_ExtMeshSetParami (extmesh,EXTMESH_LOCALRECEDE,SYS_ON); vis_ExtMeshSetParami (extmesh,EXTMESH_REVERSE,SYS_ON); vis_ExtMeshSetNormalPath (extmesh,4,1.,SYS_OFF); /* mark faces on original layer with value of 1 and faces on final layer with value of 2 */ vis_ExtMeshSetParami (extmesh,EXTMESH_FACEMARK,VIS_GEOFACE); /* create Connect object and generate */ connectext = vis_ConnectBegin (); vis_ConnectPre (connectext,SYS_DOUBLE); vis_ConnectDef (connectext,0,0); vis_ExtMeshGenerate (extmesh,connectext); if(vis_ExtMeshError (extmesh)) { printf("extrusion mesh generation error\n"); exit(1); } else { printf("extrusion mesh generation complete\n"); } /* write generated ext mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectext,SYS_NASTRAN_BULKDATA,"exam42b_ext.bdf"); /* perform tet meshing of the remaining interior */ /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numnpsurf,numelsurf,2); vis_TetMeshSetParami (tetmesh,VIS_MESH_INWARD,SYS_ON); /* fill TetMesh object with generated points on surface */ vis_ConnectNumber (connectext,SYS_ELEM,&numelext); vis_ConnectNumber (connectext,SYS_NODE,&numnpext); numnp = 0; idtran = vis_IdTranBegin (); /* find nodes on surface */ /* first generate face group */ fgroup = vis_GroupBegin (); vis_GroupDef (fgroup,numelext,SYS_ELEM,SYS_FACE); vis_ConnectSetGroupParami (connectext,CONNECT_ASSOCTYPE,VIS_GEOFACE); vis_ConnectSetGroupParami (connectext,CONNECT_ASSOCID,2); vis_ConnectKernel (connectext,0); vis_ConnectFaceGroup (connectext,CONNECT_ASSOC,NULL,fgroup); /* second generate unique node group from face group */ ngroup = vis_GroupBegin (); vis_GroupDef (ngroup,numnpext,SYS_NODE,SYS_NONE); vis_ConnectNodeGroup (connectext,CONNECT_UNIQUE,fgroup,ngroup); /* set nodes */ for(i = 1; i <= numnpext; i++) { if(!vis_GroupNode (ngroup,i)) continue; numnp++; vis_IdTranSetId (idtran,numnp,i); vis_ConnectCoordsdv (connectext,1,&i,&u); vis_TetMeshSetNode (tetmesh,numnp,u); } vis_GroupEnd (ngroup); vis_GroupEnd (fgroup); /* fill TetMesh object with generated faces on surface */ numel = 0; for(i = 1; i <= numelext; i++) { vis_ConnectElemNum (connectext,SYS_FACE,i,&num); for(no = 1; no <= num; no++) { vis_ConnectElemEntAssoc (connectext,VIS_GEOFACE,SYS_FACE,i,no,&aid); if(aid != 2) continue; vis_ConnectElemCon (connectext,SYS_FACE,i,no,&nix,ix); vis_ConnectCoordsdv (connectext,nix,ix,x); vis_IdTranIndices (idtran,nix,ix,jx); numel++; vis_TetMeshSetTri (tetmesh,numel,jx); } } /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam42b_tet.bdf"); /* merge extruded and tet meshes */ connectall = vis_ConnectBegin (); vis_ConnectPre (connectall,SYS_DOUBLE); vis_ConnectAppend (connectall,connectext); vis_ConnectAppend (connectall,connecttet); vis_ConnectSetParamf (connectall,CONNECT_TOLERANCE,0.0); vis_ConnectMerge (connectall,NULL); vis_ConnectWrite (connectall,SYS_NASTRAN_BULKDATA,"exam42b_all.bdf"); /* end objects */ free(normal); vis_IdTranEnd (idtran); vis_ConnectEnd (connectall); vis_ConnectEnd (connectext); vis_ConnectEnd (connectsurf); vis_ConnectEnd (connecttet); vis_ExtMeshEnd (extmesh); vis_SurfMeshEnd (surfmesh); vis_TetMeshEnd (tetmesh); return 0; }
The example also illustrates the usage of 3 paths in the extrusion direction, each with its own fraction of the normal distance and number of layers. Interface elements are requested at the end of each extrusion path.
The parameter EXTMESH_FACEMARK is enabled to mark all element faces at the boundaries of each extrusion path.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble x[16][3] = { {0.,1.,1.}, {1.,1.,1.}, {2.,0.,1.}, {3.,0.,1.}, {4.,1.,1.}, {5.,1.,1.}, {0.,1.,0.}, {1.,1.,0.}, {2.,0.,0.}, {3.,0.,0.}, {4.,1.,0.}, {5.,1.,0.}, {0.,2.,0.}, {5.,2.,0.}, {0.,2.,1.}, {5.,2.,1.} }; static Vdouble xn[16][3] = { { 0., 1.,0.}, { 1., 1.,0.}, { 1., 1.,0.}, {-1., 1.,0.}, {-1., 1.,0.}, { 0., 1.,0.}, { 0., 1.,0.}, { 1., 1.,0.}, { 1., 1.,0.}, {-1., 1.,0.}, {-1., 1.,0.}, { 0., 1.,0.}, { 0.,-1.,0.}, { 0.,-1.,0.}, { 0.,-1.,0.}, { 0.,-1.,0.} }; static Vint pix[6][4] = { { 1, 2, 8, 7}, { 2, 3, 9, 8}, { 3, 4,10, 9}, { 4, 5,11,10}, { 5, 6,12,11}, {13,14,16,15} }; /*---------------------------------------------------------------------- Generate an Extruded Mesh with Interface Layers ----------------------------------------------------------------------*/ int main() { vis_ExtMesh *extmesh; vis_Connect *connect; Vint numnp, numel, i, j, nix, ix[8]; Vdouble y[3]; /* create ExtMesh object */ extmesh = vis_ExtMeshBegin (); vis_ExtMeshDef (extmesh,16,6); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < 16; i++) { vis_ExtMeshSetNode (extmesh,i+1,x[i]); vis_ExtMeshSetNodeNormal (extmesh,i+1,xn[i]); } /* define linear quadrilateral connectivity */ for (i = 0; i < 6; i++) { vis_ExtMeshSetElem (extmesh,i+1,VIS_SHAPEQUAD,2,0,pix[i]); } /* set mesh parameters */ vis_ExtMeshSetParami (extmesh,EXTMESH_NORMAL,SYS_ON); vis_ExtMeshSetParami (extmesh,EXTMESH_GLOBALRECEDE,SYS_ON); vis_ExtMeshSetParami (extmesh,EXTMESH_FACEMARK,VIS_GEOFACE); /* 3 sets of layers with an interface */ vis_ExtMeshSetNormalPath (extmesh,4,0.25,SYS_ON); vis_ExtMeshSetNormalPath (extmesh,5,0.5,SYS_ON); vis_ExtMeshSetNormalPath (extmesh,4,0.25,SYS_ON); /* generate */ vis_ExtMeshGenerate (extmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,&y); printf("id= %d x= %e, y= %e, z= %e\n",i,y[0],y[1],y[2]); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix=",i); for(j = 0; j < nix; j++) { printf(" %d",ix[j]); } printf("\n"); } /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam42c.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_ExtMeshEnd (extmesh); return 0; }
Two varieties of line associations are set. The edge associations will be propagated into the final mesh as element edge entity associations on the generated triangle edges lying on the line. All nodes generated along the line will be given node associations. The line element associations will be propagated into the final mesh as element associations on all triangles bounded by the line and any other input lines.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 12 #define MAX_LINE 16 /* a square with a rectangular hole and fixed edge */ static Vdouble coords[MAX_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {.3,.3,0.}, {.7,.3,0.}, {.3,.7,0.}, {.7,.7,0.}, {.8,.8,0.}, {.91,.9,0.}, {.15,.15,0.}, {.85,.15,0.} }; /* boundary lines */ static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, {5,7}, {7,8}, {8,6}, {6,5}, {11,5}, {5,11}, {12,6}, {6,12}, {11,12}, {12,11}, /* interior edge */ {9,10}, {10,9} }; /*---------------------------------------------------------------------- Generate a 2D Planar Tri Mesh ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; Vint i, k; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[6]; Vint aid, num, aids[3]; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* set line 16 as an undivided edge */ vis_TriMeshSetLineStat (trimesh,16,0); /* tag the first line segment */ vis_TriMeshSetLineAssoc (trimesh,VIS_MISCID,1,SYS_EDGE,1001); /* elements inside region with boundary edge 10 or 13 */ vis_TriMeshSetLineAssoc (trimesh,VIS_MISCID1,10,SYS_ELEM,2000); vis_TriMeshSetLineAssoc (trimesh,VIS_MISCID1,10,SYS_ELEM,2002); vis_TriMeshSetLineAssoc (trimesh,VIS_MISCID1,13,SYS_ELEM,2001); /* tag the first node */ vis_TriMeshSetNodeAssoc (trimesh,VIS_MISCID2,1,1002); /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,1); /* set mesh size */ vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,.1); /* refine about node 1 */ vis_TriMeshSetNodeSizing (trimesh,1,.02); vis_TriMeshWrite (trimesh,SYS_ASCII,"exam43.tri"); /* generate */ vis_TriMeshGenerate (trimesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ /* check for nodes generated on tagged line segment */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %f, y= %f, z= %f\n",i,x[0],x[1],x[2]); vis_ConnectNodeAssoc (connect,VIS_MISCID2,1,&i,&aid); if(aid) { printf(" VIS_MISCID2= %d\n",aid); } } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); for(k = 1; k <= 3; k++) { vis_ConnectElemEntAssoc (connect,VIS_MISCID,SYS_EDGE,i,k,&aid); if(aid) { printf(" edge %d, VIS_MISCID= %d\n",k,aid); } } vis_ConnectAllElemAssoc (connect,VIS_MISCID1,i,&num,aids); for(k = 0; k < num; k++) { if(aids[k]) { printf(" elem, VIS_MISCID1= %d\n",aids[k]); } } } /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); return 0; }
#include <stdio.h> #include <math.h> #include "base/base.h" #include "vis/vismesh.h" #define SQUARE_NODE 8 #define SQUARE_LINE 4 /* outside square */ static Vdouble coords[SQUARE_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {1.,1.,0.}, {0.,1.,0.}, {.5,0.,0.}, {1.,.5,0.}, {.5,1.,0.}, {0.,.5,0.}}; /* square boundary lines */ static Vint lines[SQUARE_LINE][3] = { {1,5,2}, {2,6,3}, {3,7,4}, {4,8,1} }; /*---------------------------------------------------------------------- Generate a 2D Planar Tri Mesh with Parabolic Lines ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; Vint i; Vint numpts, numlns, lix[3], numcirclelines; Vint numnp, numel; Vdouble ang, rad, xc[3], x[3]; Vint nix, ix[6]; numcirclelines = 8; numpts = SQUARE_NODE + 2*numcirclelines; numlns = SQUARE_LINE + numcirclelines; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,numpts,numlns,3); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for(i = 0; i < SQUARE_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* generate circle nodes */ rad = .25; ang = 0.; xc[0] = .5; xc[1] = .5; xc[2] = 0.; for(i = 0; i < 2*numcirclelines; i++) { x[0] = rad*cos(ang) + xc[0]; x[1] = rad*sin(ang) + xc[1]; x[2] = 0. + xc[2]; ang += 3.14159/numcirclelines; vis_TriMeshSetNode (trimesh,SQUARE_NODE+i+1,x); } /* define lines */ for (i = 0; i < SQUARE_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* generate circle lines */ for(i = 0; i < numcirclelines; i++) { if(i == numcirclelines-1) { lix[0] = SQUARE_NODE+1; } else { lix[0] = SQUARE_NODE+2*i+3; } lix[1] = SQUARE_NODE+2*i+2; lix[2] = SQUARE_NODE+2*i+1; vis_TriMeshSetLine (trimesh,SQUARE_LINE+i+1,lix); } /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,1); /* set mesh size */ vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,.05); /* write debugging file */ vis_TriMeshWrite (trimesh,SYS_ASCII,"exam43a.tri"); /* generate */ vis_TriMeshGenerate (trimesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %f, y= %f, z= %f\n",i,x[0],x[1],x[2]); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); } /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43a.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 8 #define MAX_LINE 8 /* a square with a rectangular hole */ static Vdouble coords[MAX_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {.2,.2,0.}, {.8,.2,0.}, {.2,.8,0.}, {.8,.8,0.} }; static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, {5,7}, {7,8}, {8,6}, {6,5} }; /* isotropic size function */ static void s_iso(vis_TriMesh *trimesh, Vobject *usrobj, Vdouble x[3], Vdouble *s) { printf("s_iso called\n"); /* linear variation in y direction */ *s = .05 + .05*x[1]; printf("x= %e %e %e, s= %e\n",x[0],x[1],x[2],*s); } /* anisotropic size function */ static void s_aniso(vis_TriMesh *trimesh, Vobject *usrobj, Vdouble x[3], Vdouble s[3][3]) { Vdouble s1, s2, s3; printf("s_aniso called\n"); /* 4 to 1 aspect ratio at 45 degree angle */ s1 = .025; s[0][0] = s1*.707; s[0][1] = s1*.707; s[0][2] = 0.; s2 = .1; s[1][0] = s2*-.707; s[1][1] = s2*.707; s[1][2] = 0.; /* set the out of plane direction size to unity */ s3 = 1.; s[2][0] = 0.; s[2][1] = 0.; s[2][2] = s3*1.; printf("x= %e %e %e, s1= %e, s2= %e\n",x[0],x[1],x[2],s1,s2); } /*---------------------------------------------------------------------- Generate a 2D Planar Tri Mesh with Sizing Function ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; Vint i, k; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[6]; Vint aid; Vint anisoflag; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* tag the first line segment */ vis_TriMeshSetLineAssoc (trimesh,VIS_MISCID,1,SYS_EDGE,1001); /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,VIS_ON); /* use zero for isotropic sizing, one for anisotropic */ anisoflag = 1; /* set sizing function */ if(anisoflag == 0) { vis_TriMeshSetFunction (trimesh,TRIMESH_FUN_SIZING,(Vfunc*)s_iso,NULL); } else { vis_TriMeshSetFunction (trimesh,TRIMESH_FUN_ASIZING,(Vfunc*)s_aniso,NULL); } vis_TriMeshWrite (trimesh,SYS_ASCII,"exam43b.tri"); /* generate */ vis_TriMeshGenerate (trimesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); } /* print element information */ /* check for edges generated on tagged line segment */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); for(k = 1; k <= 3; k++) { vis_ConnectElemEntAssoc (connect,VIS_MISCID,SYS_EDGE,i,k,&aid); if(aid) { printf(" edge %d, VIS_MISCID= %d\n",k,aid); } } } /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43b.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); return 0; }
The planar geometry consists of a unit square with a fixed interior edge. The desired goal of TriMesh is to generate a triangulation of the input geometry without generating any additional nodes on the boundary or interior. Do this by calling vis_TriMeshSetParami and disable the parameters VIS_MESH_BOUNDREFINE and VIS_MESH_INTERREFINE. It is useful to know which edges of the generated triangles lie on input boundary lines. Use vis_TriMeshSetParami and set line flag association to VIS_MISCID1. This will enable generation of the element association consisting of bitwise flags of triangle edges which lie on input boundary lines. The triangle mesh is generated using vis_TriMeshGenerate. The generated triangle mesh is illustrated in the first figure below. Note that the number of nodes in the output Connect object, numnp is equal to the number of nodes (MAX_NODE) input to TriMesh. These nodes are set in SurfMesh using vis_SurfMeshSetPoint. The triangles are set using vis_SurfMeshSetTri. The edge flags are queried using vis_ConnectElemAssoc with association type VIS_MISCID1. The edge flags are parsed bit by bit and the corresponding triangle edges are marked as preserved. Use vis_SurfMeshSetParami and vis_SurfMeshSetParamd to set meshing parameters. In this case linear quadrilateral elements are generated with a mesh size of .1. Note that the preserved edges appear in the final mesh. The generated quadrilateral mesh is illustrated in the second figure below.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 6 #define MAX_LINE 6 /* a square with a fixed interior edge */ static Vdouble coords[MAX_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {.2,.3,0.}, {.7,.8,0.} }; /* boundary lines */ static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, /* interior edge */ {5,6}, {6,5} }; /*---------------------------------------------------------------------- Generate a 2D Planar Quad Surface Mesh ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect, *connectsurf; vis_SurfMesh *surfmesh; Vint i, j; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[6], efl[3]; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* generate boundary triangulation only */ vis_TriMeshSetParami (trimesh,VIS_MESH_BOUNDREFINE,VIS_OFF); vis_TriMeshSetParami (trimesh,VIS_MESH_INTERREFINE,VIS_OFF); /* element associations with line flags */ vis_TriMeshSetParami (trimesh,TRIMESH_LINEFLAG,VIS_MISCID1); /* generate */ vis_TriMeshWrite (trimesh,SYS_ASCII,"exam43c.tri"); vis_TriMeshGenerate (trimesh,connect); /* delete */ vis_TriMeshEnd (trimesh); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("TriMesh, numnp= %d, numel= %d\n",numnp,numel); surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numnp,numel); /* create connect object to receive surf mesh */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* load nodes and preserve them */ for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_SurfMeshSetPoint (surfmesh,i,x,1); } /* load elements */ for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); for(j = 0; j < 3; j++) { vis_ConnectElemEntAssoc (connect,VIS_MISCID1,SYS_EDGE,i,j+1,&efl[j]); } vis_SurfMeshSetTri (surfmesh,i,ix,efl); } /* delete */ vis_ConnectEnd (connect); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,VIS_MESH_SHAPE,VIS_SHAPEQUAD); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.1); /* generate */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam43c.srf"); vis_SurfMeshGenerate (surfmesh,connectsurf); /* print generated nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numnp); vis_ConnectNumber (connectsurf,SYS_ELEM,&numel); printf("SurfMesh, numnp= %d, numel= %d\n",numnp,numel); /* write out NASTRAN bulk data file */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam43c.bdf"); /* end objects */ vis_ConnectEnd (connectsurf); vis_SurfMeshEnd (surfmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 8 #define MAX_LINE 8 /* a square with a rectangular hole */ static Vdouble coords[MAX_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {.2,.2,0.}, {.8,.2,0.}, {.2,.8,0.}, {.8,.8,0.} }; static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, {5,7}, {7,8}, {8,6}, {6,5} }; /*---------------------------------------------------------------------- Refine a 2D Planar Tri Mesh ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; vis_State *state; Vint i; Vint numnp, numel; Vdouble x[3], v; Vint nix, ix[6]; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,VIS_ON); vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,.2); /* generate initial mesh */ vis_TriMeshGenerate (trimesh,connect); vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Generated original mesh\n"); printf("numnp= %d\n",numnp); printf("numel= %d\n",numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43d.bdf"); /* create State object with new element edge lengths */ state = vis_StateBegin (); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); /* refine elements in upper right corner */ for(i = 1; i <= numel; ++i) { vis_ConnectElemNode (connect,i,&nix,ix); vis_ConnectCoordsdv (connect,1,&ix[0],(Vdouble(*)[3])x); if(x[0] >= .8 && x[1] >= .8) { v = .1; vis_StateSetDatadv (state,i,&v); } } /* clear Connect object */ vis_ConnectDef (connect,0,0); /* generate refined mesh */ vis_TriMeshRefine (trimesh,state,connect); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43d.ref.bdf"); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Generated refined mesh\n"); printf("numnp= %d\n",numnp); printf("numel= %d\n",numel); /* print node information */ /* check for nodes generated on tagged line segment */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); } /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); vis_StateEnd (state); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 8 #define MAX_LINE 8 /* a square with a rectangular hole */ static Vdouble coords[MAX_NODE][3] = { 0.,0.,0., 1.,0.,0., 0.,1.,0., 1.,1.,0., .2,.2,0., .8,.2,0., .2,.8,0., .8,.8,0. }; static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, {5,7}, {7,8}, {8,6}, {6,5} }; /*---------------------------------------------------------------------- Refine a 2D Planar Tri Mesh as on Orphan Mesh ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; vis_State *state; Vint i; Vint numnp, numel; Vdouble x[3], v; Vint nix, ix[6]; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,VIS_ON); vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,.2); /* generate initial mesh */ vis_TriMeshGenerate (trimesh,connect); vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Generated original mesh\n"); printf("numnp= %d\n",numnp); printf("numel= %d\n",numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43e.bdf"); /* redefine trimesh to setup as taking orphan mesh */ vis_TriMeshDef (trimesh,numnp,MAX_LINE,2); for (i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,&x); vis_TriMeshSetNode (trimesh,i,x); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* set trimesh as background mesh */ for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); vis_TriMeshSetElem (trimesh,i,SYS_SHAPETRI,3,ix); } /* create State object with new element edge lengths */ state = vis_StateBegin (); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); /* refine elements in upper right corner */ for(i = 1; i <= numel; ++i) { vis_ConnectElemNode (connect,i,&nix,ix); vis_ConnectCoordsdv (connect,1,&ix[0],(Vdouble(*)[3])x); if(x[0] >= .8 && x[1] >= .8) { v = .1; vis_StateSetDatadv (state,i,&v); } } /* clear Connect object */ vis_ConnectDef (connect,0,0); /* generate refined mesh */ vis_TriMeshRefine (trimesh,state,connect); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43e_ref.bdf"); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Generated refined mesh\n"); printf("numnp= %d\n",numnp); printf("numel= %d\n",numel); /* print node information */ /* check for nodes generated on tagged line segment */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5]); } /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); vis_StateEnd (state); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 7 #define MAX_LINE 8 /* 2 x 1 rectangle divided in the middle into two regions */ static Vdouble coords[MAX_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {2.,0.,0.}, {2.,1.,0.}, {.5,.5,0.} }; /* boundary lines of two regions */ static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, {2,5}, {5,6}, {6,4}, {4,2} }; /*---------------------------------------------------------------------- Generate a 2D Planar Tri Mesh with Sizing ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; Vint i; Vint numnp, numel; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* tag the two regions */ vis_TriMeshSetLineAssoc (trimesh,VIS_GEOBODY,1,SYS_ELEM,1); vis_TriMeshSetLineAssoc (trimesh,VIS_GEOBODY,5,SYS_ELEM,2); /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,1); /* allow unconnected node */ vis_TriMeshSetParami (trimesh,TRIMESH_UNCONNECT,SYS_ON); /* set mesh size */ vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,.2); /* refine about node 7 in region 1 */ vis_TriMeshSetNodeSizing (trimesh,7,.01); /* refine edge 4 in region 1 */ vis_TriMeshSetLineSizing (trimesh,4,SYS_EDGE,.05); /* refine region 2 */ vis_TriMeshSetLineSizing (trimesh,5,SYS_ELEM,.05); vis_TriMeshWrite (trimesh,SYS_ASCII,"exam43f.tri"); /* generate */ vis_TriMeshGenerate (trimesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43f.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #define MAX_NODE 6 #define MAX_LINE 8 /* 2 x 1 rectangle divided in the middle into two regions */ static Vdouble coords[MAX_NODE][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {2.,0.,0.}, {2.,1.,0.} }; /* boundary lines of two regions */ static Vint lines[MAX_LINE][2] = { {1,2}, {2,4}, {4,3}, {3,1}, {2,5}, {5,6}, {6,4}, {4,2} }; /*---------------------------------------------------------------------- Generate a 2D Planar Tri Mesh with Interior Sizing ----------------------------------------------------------------------*/ int main() { vis_TriMesh *trimesh; vis_Connect *connect; Vint i; Vint numnp, numel; Vdouble xo[3], xa[3], xb[3], d[3]; /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,MAX_NODE,MAX_LINE,2); /* create connect object to receive mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < MAX_NODE; i++) { vis_TriMeshSetNode (trimesh,i+1,coords[i]); } /* define lines */ for (i = 0; i < MAX_LINE; i++) { vis_TriMeshSetLine (trimesh,i+1,lines[i]); } /* define line depth sizing in region 2 */ for (i = 4; i < MAX_LINE; i++) { vis_TriMeshSetLineDepthSizing (trimesh,i+1,.1,.02); } /* tag the two regions */ vis_TriMeshSetLineAssoc (trimesh,VIS_GEOBODY,1,SYS_ELEM,1); vis_TriMeshSetLineAssoc (trimesh,VIS_GEOBODY,5,SYS_ELEM,2); /* generate quadratic elements */ vis_TriMeshSetParami (trimesh,VIS_MESH_MAXI,3); vis_TriMeshSetParami (trimesh,TRIMESH_SMOOTH,1); /* set mesh size */ vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,.2); /* interior ellipsoidal shape for sizing */ /* positioned in center of cube */ xo[0] = .5; xo[1] = .5; xo[2] = 0.; /* oriented along x axis and at 45 degrees in y-z plane */ xa[0] = 1.0; xa[1] = .5; xa[2] = .5; xb[0] = .5; xb[1] = 1.0; xb[2] = .5; /* lengths of ellipsoid along each axis */ d[0] = .05; d[1] = .15; d[2] = .25; vis_TriMeshSetGeomSizing (trimesh,VIS_MESH_GEOMSPHERE,xo,xa,xb,d,0.02); vis_TriMeshWrite (trimesh,SYS_ASCII,"exam43g.tri"); /* generate */ vis_TriMeshGenerate (trimesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* write out NASTRAN bulk data file */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam43g.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TriMeshEnd (trimesh); return 0; }
The nodes and finite elements are actually generated by calling vis_TetMeshGenerate. In this simple case no internal nodes are generated. The generated nodes and elements are entered into the Connect object which is passed in the argument list. Lastly, the generated nodes and elements are printed.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; /*---------------------------------------------------------------------- Generate a 3D Volume Tet Mesh ----------------------------------------------------------------------*/ int main() { vis_TetMesh *tetmesh; vis_Connect *connect; Vint i, j; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[4]; Vint num, aid, aids[10]; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,8,12,2); /* create connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < 8; i++) { vis_TetMeshSetNode (tetmesh,i+1,coords[i]); } /* define tris */ for (i = 0; i < 12; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); } /* define a node association on node 2 */ vis_TetMeshSetNodeAssoc (tetmesh,VIS_GEOVERT,2,1000); /* define an element edge association on tri 4, edge 2 */ vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOEDGE,4,SYS_EDGE,2,10); /* define an element face association on tri 3 */ vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOFACE,3,SYS_FACE,1,100); /* define an element association on tri 3 */ vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOBODY,3,SYS_ELEM,0,200); vis_TetMeshSetTriAssoc (tetmesh,VIS_PROPID,3,SYS_ELEM,0,1); /* set edgelength */ vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,1.); vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam44.tet"); /* generate */ vis_TetMeshGenerate (tetmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %f, y= %f, z= %f\n", i,x[0],x[1],x[2]); } /* node associations */ for(i = 1; i <= numnp; i++) { vis_ConnectAllNodeAssoc (connect,VIS_GEOVERT,i,&num,aids); for(j = 0; j < num; j++) { if(aids[j] == 0) continue; printf("id= %d aid[%d]= %d\n",i,j,aids[j]); } } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3]); } /* element entity associations */ for(i = 1; i <= numel; i++) { /* tet edges */ for(j = 1; j <= 6; j++) { vis_ConnectElemEntAssoc (connect,VIS_GEOEDGE,SYS_EDGE,i,j,&aid); if(aid == 0) continue; printf("id= %d edge= %d, aid= %d\n",i,j,aid); } /* tet faces */ for(j = 1; j <= 4; j++) { vis_ConnectElemEntAssoc (connect,VIS_GEOFACE,SYS_FACE,i,j,&aid); if(aid == 0) continue; printf("id= %d face= %d, aid= %d\n",i,j,aid); } } vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam44.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TetMeshEnd (tetmesh); return 0; }
A monitor function has been installed to follow the progress of the meshing process. The function vis_TetMeshGetInteger is called with type VIS_MESH_PROGRESS within the monitor function to query and print the current state of the meshing process.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* fixed node points */ static Vdouble coords[25][3] = { {0.,0.,0.}, {5.,0.,0.}, {0.,3.,0.}, {5.,3.,0.}, {0.,0.,3.}, {5.,0.,3.}, {0.,3.,3.}, {5.,3.,3.}, /* unit cube void */ {1.,1.,1.}, {2.,1.,1.}, {1.,2.,1.}, {2.,2.,1.}, {1.,1.,2.}, {2.,1.,2.}, {1.,2.,2.}, {2.,2.,2.}, /* interior baffle face */ {3.,1.,1.}, {3.,1.,2.}, /* interior edge */ {4.,2.,1.}, {4.,2.,2.}, /* interior point */ {3.,2.,1.}, /* interior floating face */ {3.5,1.,1.}, {3.5,1.,2.}, {4.5,1.,1.}, {4.5,1.,2.} }; /* surface triangles */ static Vint tris[32][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, /* unit cube void */ {9,11,13}, {11,15,13}, {12,10,14}, {16,12,14}, {9,13,10}, {13,14,10}, {15,11,12}, {16,15,12}, {9,10,12}, {12,11,9}, {13,15,16}, {13,16,14}, /* interior double backed triangles */ {14,18,10}, {14,10,18}, {10,18,17}, {10,17,18}, /* interior double backed floating triangles */ {22,25,24}, {22,24,25}, {23,22,25}, {23,25,22} }; /* interior edge */ static Vint inedge[2] = { 19,20 }; /*---------------------------------------------------------------------- monitor function ----------------------------------------------------------------------*/ static void monitor(vis_TetMesh *tetmesh, Vobject *usrobj) { int iparam[4]; printf("monitor called\n"); /* query and print progress */ vis_TetMeshGetInteger (tetmesh,VIS_MESH_PROGRESS,iparam); printf("phase= %d\n",iparam[0]); printf("numnp= %d\n",iparam[1]); printf("numel= %d\n",iparam[2]); printf("percent= %d\n",iparam[3]); } /*---------------------------------------------------------------------- Generate a 3D Volume Tet Mesh with Interior Features ----------------------------------------------------------------------*/ int main() { vis_TetMesh *tetmesh; vis_Connect *connect; Vint i; Vint numnode, numtris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[4]; /* number of nodes */ numnode = 25; /* number of triangles */ numtris = 32; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numnode,numtris,2); /* create connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < numnode; i++) { vis_TetMeshSetNode (tetmesh,i+1,coords[i]); } /* define tris */ for (i = 0; i < numtris; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); } /* define interior edge */ vis_TetMeshSetEdge (tetmesh,1,inedge); /* allow unconnected nodes */ vis_TetMeshSetParami (tetmesh,TETMESH_UNCONNECT,VIS_ON); /* set monitor function */ vis_TetMeshSetFunction (tetmesh,TETMESH_FUN_MONITOR,(Vfunc*)monitor,NULL); /* generate */ vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam44a.tet"); vis_TetMeshGenerate (tetmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %f, y= %f, z= %f\n", i,x[0],x[1],x[2]); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3]); } vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam44a.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TetMeshEnd (tetmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; /*---------------------------------------------------------------------- Generate a 3D Volume Tet Mesh ----------------------------------------------------------------------*/ int main() { vis_TetMesh *tetmesh; vis_Connect *connect; vis_State *state; Vint i, j; Vint numnp, numel; Vdouble x[3], v; Vint nix, ix[4]; Vint num, aid, aids[10]; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,8,12,2); /* create connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < 8; i++) { vis_TetMeshSetNode (tetmesh,i+1,coords[i]); } /* define tris */ for (i = 0; i < 12; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); } /* define a node association on node 2 */ vis_TetMeshSetNodeAssoc (tetmesh,VIS_GEOVERT,2,1000); /* define an element edge association on tri 4, edge 2 */ vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOEDGE,4,SYS_EDGE,2,10); /* define an element face association on tri 3 */ vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOFACE,3,SYS_FACE,1,100); vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam44b.tet"); /* generate */ vis_TetMeshGenerate (tetmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %f, y= %f, z= %f\n", i,x[0],x[1],x[2]); } /* node associations */ for(i = 1; i <= numnp; i++) { vis_ConnectAllNodeAssoc (connect,VIS_GEOVERT,i,&num,aids); for(j = 0; j < num; j++) { if(aids[j] == 0) continue; printf("id= %d aid[%d]= %d\n",i,j,aids[j]); } } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d %d\n", i,ix[0],ix[1],ix[2],ix[3]); } /* element entity associations */ for(i = 1; i <= numel; i++) { /* tet edges */ for(j = 1; j <= 6; j++) { vis_ConnectElemEntAssoc (connect,VIS_GEOEDGE,SYS_EDGE,i,j,&aid); if(aid == 0) continue; printf("id= %d edge= %d, aid= %d\n",i,j,aid); } /* tet faces */ for(j = 1; j <= 4; j++) { vis_ConnectElemEntAssoc (connect,VIS_GEOFACE,SYS_FACE,i,j,&aid); if(aid == 0) continue; printf("id= %d face= %d, aid= %d\n",i,j,aid); } } vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam44b.bdf"); state = vis_StateBegin (); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); for(i = 1; i <= numel; ++i) { v = .5; vis_StateSetDatadv (state,i,&v); } vis_StateWrite (state,NULL,SYS_ASCII,"exam44b.tet.sta1"); vis_ConnectDef (connect,0,0); vis_TetMeshRefine (tetmesh,state,connect); vis_StateEnd (state); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam44b.ref.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_TetMeshEnd (tetmesh); return 0; }
A uniform new mesh size of 0.25 is employed throughout the volume, as this constant value is set in the State object required for the refinement process.
#include <stdio.h> #include <math.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint eassoc[12][3] = { {1,0,2}, {0,3,4}, {0,5,6}, {7,0,8}, {9,0,0}, {0,0,10}, {0,11,0}, {0,0,12}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }; static Vint maxi = 2; /*---------------------------------------------------------------------- Generate a 3D Volume Tet Mesh and Refine it as an Orphan Mesh ----------------------------------------------------------------------*/ int main() { vis_TetMesh *tetmesh; vis_Connect *connect1, *connect2; vis_State *state; Vint i, j; Vint numnp, numel; Vdouble x[3], size; Vint nix, ix[4]; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,8,12,maxi); /* create connect object */ connect1 = vis_ConnectBegin (); vis_ConnectPre (connect1,SYS_DOUBLE); vis_ConnectDef (connect1,0,0); /* define nodes */ for (i = 0; i < 8; i++) { vis_TetMeshSetNode (tetmesh,i+1,coords[i]); vis_TetMeshSetNodeAssoc (tetmesh,VIS_GEOVERT,i+1,i+1); } /* define tris */ for (i = 0; i < 12; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); for(j = 0; j < 3; ++j) { if(eassoc[i][j]) { vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1, eassoc[i][j]); } } } /* generate */ vis_TetMeshGenerate (tetmesh,connect1); vis_ConnectNumber (connect1,SYS_NODE,&numnp); vis_ConnectNumber (connect1,SYS_ELEM,&numel); printf("Generated original mesh\n"); printf("numnp= %d\n",numnp); printf("numel= %d\n",numel); vis_ConnectWrite (connect1,SYS_NASTRAN_BULKDATA,"exam44c_orig.bdf"); /* redefine tetmesh to setup as taking orphan mesh */ vis_TetMeshDef (tetmesh,numnp,12,maxi); /* define nodes */ for (i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect1,1,&i,&x); vis_TetMeshSetNode (tetmesh,i,x); vis_TetMeshSetNodeAssoc (tetmesh,VIS_GEOVERT,i,i); } /* define tris */ for (i = 0; i < 12; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); for(j = 0; j < 3; ++j) { if(eassoc[i][j]) { vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1, eassoc[i][j]); } } } /* set tetmesh as background mesh */ for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect1,i,&nix,ix); vis_TetMeshSetElem (tetmesh,i,SYS_SHAPETET,maxi,ix); } /* create state object with new sizes */ state = vis_StateBegin (); vis_StatePre (state,SYS_DOUBLE); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); size = 0.25; for(i = 1; i <= numel; i++) { vis_StateSetDatadv (state,i,&size); } /* refine mesh */ connect2 = vis_ConnectBegin (); vis_ConnectPre (connect2,SYS_DOUBLE); vis_ConnectDef (connect2,0,0); vis_TetMeshRefine (tetmesh,state,connect2); vis_ConnectNumber (connect2,SYS_NODE,&numnp); vis_ConnectNumber (connect2,SYS_ELEM,&numel); printf("Generated refined mesh\n"); printf("numnp= %d\n",numnp); printf("numel= %d\n",numel); vis_ConnectWrite (connect2,SYS_NASTRAN_BULKDATA,"exam44c_ref.bdf"); /* end objects */ vis_ConnectEnd (connect1); vis_ConnectEnd (connect2); vis_TetMeshEnd (tetmesh); vis_StateEnd (state); return 0; }
The example also illustrates the ability of the vis_TetMeshRefine method to be called several times. For simplicity, the uniform mesh size is halved from one refinement step to another.
#include <stdio.h> #include <math.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint maxi = 2; static Vint eassoc[12][3] = { {1,0,2}, {0,3,4}, {0,5,6}, {7,0,8}, {9,0,0}, {0,0,10}, {0,11,0}, {0,0,12}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }; /*---------------------------------------------------------------------- Generate a Linear 3D Volume Tet Mesh and Perform Successive Refinements ----------------------------------------------------------------------*/ int main() { vis_TetMesh *tetmesh; vis_Connect *connect1, *connect2, *connecttmp; vis_State *state; vis_GridFun *gf; Vint i, j, iref; Vint numel; Vdouble size; Vchar buffer[80]; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,8,12,maxi); /* create connect object */ connect1 = vis_ConnectBegin (); vis_ConnectPre (connect1,SYS_DOUBLE); vis_ConnectDef (connect1,0,0); /* define nodes */ for (i = 0; i < 8; i++) { vis_TetMeshSetNode (tetmesh,i+1,coords[i]); /* define a node association on every vertex */ vis_TetMeshSetNodeAssoc (tetmesh,VIS_GEOVERT,i+1,i+1); } /* define tris */ for (i = 0; i < 12; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); for(j = 0; j < 3; ++j) { if(eassoc[i][j]) { vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1, eassoc[i][j]); } } } /* define an element edge association on tri 4, edge 2 */ vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam44.tet"); /* generate */ vis_TetMeshGenerate (tetmesh,connect1); vis_ConnectNumber (connect1,SYS_ELEM,&numel); printf("Generated original mesh\n"); vis_ConnectWrite (connect1,SYS_NASTRAN_BULKDATA,"exam44d_orig.bdf"); /* create state object with new sizes and refine */ gf = vis_GridFunBegin(); state = vis_StateBegin (); vis_StateSetObject (state,VIS_GRIDFUN,(Vobject*)gf); connect2 = vis_ConnectBegin (); vis_ConnectPre (connect2,SYS_DOUBLE); size = 1.; for(iref = 0; iref < 3; ++iref) { size *= 0.5; vis_ConnectGridFun (connect1,gf); vis_StatePre (state,SYS_DOUBLE); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); for(i = 1; i <= numel; i++) { vis_StateSetDatadv (state,i,&size); } /* refine mesh */ vis_ConnectDef (connect2,0,0); vis_TetMeshRefine (tetmesh,state,connect2); printf("Generated refined mesh %d\n",iref+1); sprintf(buffer,"exam44d_ref%d.bdf",iref+1); vis_ConnectWrite (connect2,SYS_NASTRAN_BULKDATA,buffer); vis_ConnectNumber (connect2,SYS_ELEM,&numel); /* swap connect objects */ connecttmp = connect1; connect1 = connect2; connect2 = connecttmp; } /* end objects */ vis_ConnectEnd (connect1); vis_ConnectEnd (connect2); vis_TetMeshEnd (tetmesh); vis_StateEnd (state); vis_GridFunEnd (gf); return 0; }
#include <stdio.h> #include <math.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[26][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {.5,0.,0.}, {1.,.5,0.}, {.5,1.,0.}, {0.,.5,0.}, {.5,0.,1.}, {1.,.5,1.}, {.5,1.,1.}, {0.,.5,1.}, {0.,0.,.5}, {1.,0.,.5}, {0.,1.,.5}, {1.,1.,.5}, {.5,.5,0.}, {.5,.5,1.}, {0.,.5,.5}, {1.,.5,.5}, {.5,0.,.5}, {.5,1.,.5} }; static Vint tris[12][6] = { { 1, 5, 3,17,23,12}, { 3, 5, 7,23,16,19}, { 4, 6, 2,24,18,10}, { 8, 6, 4,14,24,20}, { 1, 2, 5, 9,25,17}, { 5, 2, 6,25,18,13}, { 7, 4, 3,26,11,19}, { 8, 4, 7,20,26,15}, { 1, 4, 2,21,10, 9}, { 4, 1, 3,21,12,11}, { 5, 8, 7,22,15,16}, { 5, 6, 8,13,14,22} }; static Vint maxi = 3; static Vint eassoc[12][3] = { { 1, 0, 2}, { 0, 3, 4}, { 0, 5, 6}, { 7, 0, 8}, { 9, 0, 0}, { 0, 0,10}, { 0,11, 0}, { 0, 0,12}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0} }; /*---------------------------------------------------------------------- Generate a Quadratic 3D Volume Tet Mesh and Perform Successive Refinements ----------------------------------------------------------------------*/ int main() { vis_TetMesh *tetmesh; vis_Connect *connect1, *connect2, *connecttmp; vis_State *state; vis_GridFun *gf; Vint i, j, iref; Vint numel; Vdouble size; Vchar buffer[80]; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,26,12,maxi); /* create connect object */ connect1 = vis_ConnectBegin (); vis_ConnectPre (connect1,SYS_DOUBLE); vis_ConnectDef (connect1,0,0); /* define nodes */ for (i = 0; i < 26; i++) { vis_TetMeshSetNode (tetmesh,i+1,coords[i]); /* define a node association on every corner vertex */ if(i < 8) { vis_TetMeshSetNodeAssoc (tetmesh,VIS_GEOVERT,i+1,i+1); } } /* define tris */ for (i = 0; i < 12; i++) { vis_TetMeshSetTri (tetmesh,i+1,tris[i]); for(j = 0; j < 3; ++j) { if(eassoc[i][j]) { vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1, eassoc[i][j]); } } } vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam44e.tet"); /* generate */ vis_TetMeshGenerate (tetmesh,connect1); vis_ConnectNumber (connect1,SYS_ELEM,&numel); printf("Generated original mesh\n"); vis_ConnectWrite (connect1,SYS_NASTRAN_BULKDATA,"exam44e_orig.bdf"); /* create state object with new sizes and refine */ gf = vis_GridFunBegin(); state = vis_StateBegin (); vis_StateSetObject (state,VIS_GRIDFUN,(Vobject*)gf); connect2 = vis_ConnectBegin (); vis_ConnectPre (connect2,SYS_DOUBLE); size = 1.; for(iref = 0; iref < 3; ++iref) { size *= 0.5; vis_ConnectGridFun (connect1,gf); vis_StatePre (state,SYS_DOUBLE); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); for(i = 1; i <= numel; i++) { vis_StateSetDatadv (state,i,&size); } /* refine mesh */ vis_ConnectDef (connect2,0,0); vis_TetMeshRefine (tetmesh,state,connect2); printf("Generated refined mesh %d\n",iref+1); sprintf(buffer,"exam44e_ref%d.bdf",iref+1); vis_ConnectWrite (connect2,SYS_NASTRAN_BULKDATA,buffer); vis_ConnectNumber (connect2,SYS_ELEM,&numel); /* swap connect objects */ connecttmp = connect1; connect1 = connect2; connect2 = connecttmp; } /* end objects */ vis_ConnectEnd (connect1); vis_ConnectEnd (connect2); vis_TetMeshEnd (tetmesh); vis_StateEnd (state); vis_GridFunEnd (gf); return 0; }
The geometry points are defined and assigned the VIS_GEOVERT point association type. The value of the association is set to the point id. The nodes in the surface mesh generated by SurfMesh and the nodes in the final volume mesh generated by TetMesh which lie on these geometry points will have the VIS_GEOVERT node association type set to the original defined point id value.
The triangle edges are assigned VIS_GEOEDGE element entity association values set to the edge ids in the range 1-12. The triangle faces are assigned the VIS_GEOFACE element entity association values set to the face ids in the range 1-6. Finally the triangles are assigned VIS_GEOBODY element association values of 1, since there is only a single body. All tetrahedra edges lying on geometry edges will be given VIS_GEOEDGE element entity associations, all tetrahedra faces lying on geometry faces will be given VIS_GEOFACE element entity associations, and all tetrahedra will be given VIS_GEOBODY element associations.
The parameter, maxi is set to 3 to generate parabolic elements throughout. Setting the parameter to 2 will generate linear elements. The final output of the TetMesh object which is placed in a Connect object is both printed and written to a NASTRAN bulk data file.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* 3----3-----4 /. /| / 4 / 2 12 . 11 | / 1....1./...2 7----7-----8 / | 9 | 10 8 . 6 / |. |/ 5----5-----6 faces are ordered 1(-z), 2(+z) 3(-y) 4(+y) 5(-x) 6(+x) y | +-- x / z */ /* a simple unit cube */ static Vdouble xc[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint tefl[12][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; /* edge associations */ static Vint ted[12][3] = { {9,0,4}, {0,8,12}, {0,10,2}, {1,0,11}, {1,0,9}, {0,10,5}, {0,3,12}, {11,0,7}, {0,2,1}, {0,4,3}, {0,7,8}, {5,6,0} }; /* face associations */ static Vint tfa[12] = { 5,5, 6,6, 3,3, 4,4, 1,1, 2,2 }; /* triangle normals */ static Vdouble norms[12][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Surface Mesh and Tet Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connecttet; Vint i, j, k; Vint maxi; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[10]; Vint num, aid, aids[10]; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,8,12); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* generate parabolic elements */ maxi = 3; /* define points */ for (i = 0; i < 8; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); /* set VIS_GEOVERT association to the point id */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_GEOVERT,i+1,i+1); } /* define triangle connectivity */ for (i = 0; i < 12; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); /* set VIS_GEOEDGE and VIS_GEOFACE */ for(j = 0; j < 3; j++) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1, ted[i][j]); } vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,i+1,SYS_FACE,0,tfa[i]); /* set VIS_GEOBODY to 1, only a single body */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,0,1); } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,maxi); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.5); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam45.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam45_srf.bdf"); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,maxi); /* Fill TetMesh object with generated points on surface */ vis_TetMeshConnect (tetmesh,connectsurf); /* set mesh parameters */ vis_TetMeshSetParami (tetmesh,VIS_MESH_MAXI,maxi); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,.5); /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of tets = %d\n",numel); /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam45_tet.bdf"); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connecttet,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %e, y= %e, z= %e\n",i,x[0],x[1],x[2]); } /* node associations */ for(i = 1; i <= numnp; i++) { vis_ConnectAllNodeAssoc (connecttet,VIS_GEOVERT,i,&num,aids); for(j = 0; j < num; j++) { if(aids[j] == 0) continue; printf("id= %d, VIS_GEOVERT[%d]= %d\n",i,j,aids[j]); } } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connecttet,i,&nix,ix); printf("id= %d ix=",i); for(j = 0; j < nix; j++) { printf(" %d",ix[j]); } printf("\n"); } /* element associations */ for(i = 1; i <= numel; i++) { vis_ConnectElemAssoc (connecttet,VIS_GEOBODY,1,&i,&aid); if(aid == 0) continue; printf("id= %d, VIS_GEOBODY= %d\n",i,aid); } /* element entity associations */ for(i = 1; i <= numel; i++) { /* tet edges */ for(j = 1; j <= 6; j++) { vis_ConnectAllElemEntAssoc (connecttet,VIS_GEOEDGE,SYS_EDGE,i,j, &num,aids); for(k = 0; k < num; k++) { if(aids[k] == 0) continue; printf("id= %d edge= %d, VIS_GEOEDGE[%d]= %d\n",i,j,k,aids[k]); } } /* tet faces */ for(j = 1; j <= 4; j++) { vis_ConnectElemEntAssoc (connecttet,VIS_GEOFACE,SYS_FACE,i,j,&aid); if(aid == 0) continue; printf("id= %d face= %d, VIS_GEOFACE= %d\n",i,j,aid); } } /* end objects */ vis_ConnectEnd (connectsurf); vis_ConnectEnd (connecttet); vis_SurfMeshEnd (surfmesh); vis_TetMeshEnd (tetmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* a cube with interior surface */ /* point coordinates */ static Vdouble xc[12][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,0.,2.}, {1.,0.,2.}, {0.,1.,2.}, {1.,1.,2.} }; /* triangle connectivity */ static Vint tris[22][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,9,7}, {7,9,11}, {8,10,6}, {12,10,8}, {5,6,9}, {9,6,10}, {11,8,7}, {12,8,11}, {9,12,11}, {9,10,12} }; /* triangle right and left element associations */ static Vint ta[22][2] = { /* outer boundary and non-manifold internal surface */ {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,2}, {1,2}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0} }; /* triangle edge flags */ static Vint tefl[22][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {1,1,0} }; /* triangle normals */ static Vdouble norms[22][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate Surface and 3D Volume Tet Mesh with Sizing ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connecttet; Vint i; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[3], aid; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,12,22); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 12; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 22; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); vis_SurfMeshSetTriBack (surfmesh,i+1,ta[i][0],ta[i][1]); /* set property associations */ if(ta[i][0]) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,0,ta[i][0]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,ta[i][0]); } if(ta[i][1]) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,-1,ta[i][1]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,-1,ta[i][1]); } } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.2); /* write out file encapsulating meshing specifications */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam45a.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } vis_SurfMeshEnd (surfmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam45a-srf.bdf"); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts+1,numsurftris,2); /* Fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* Fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_TetMeshSetTri (tetmesh,i,ix); vis_ConnectElemAssoc (connectsurf,VIS_PROPID,1,&i,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_PROPID,i,SYS_ELEM,0,aid); } vis_ConnectElemAssoc (connectsurf,VIS_GEOBODY,1,&i,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOBODY,i,SYS_ELEM,0,aid); } } /* set sizing */ vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,.2); /* add sizing at unconnected node in center of region 1 */ x[0] = .5; x[1] = .5; x[2] = .5; vis_TetMeshSetNode (tetmesh,numsurfpnts+1,x); vis_TetMeshSetNodeSizing (tetmesh,numsurfpnts+1,.02); vis_TetMeshSetParami (tetmesh,TETMESH_UNCONNECT,SYS_ON); /* set region sizing */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemAssoc (connectsurf,VIS_GEOBODY,1,&i,&aid); if(aid == 2) { vis_TetMeshSetTriSizing (tetmesh,i,.05); } } vis_ConnectEnd (connectsurf); /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* write out file encapsulating meshing specifications */ vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam45a.tet"); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } vis_TetMeshEnd (tetmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam45a-tet.bdf"); vis_ConnectEnd (connecttet); return 0; }
A line association is defined along input line 1. As a result all nodes generated along input line 1 will be given the the specified association. In a similar manner, a point association is defined at point 5. The node generated under the point will be given the specified association.
The density of the generated mesh and the order of line elements to generate are specified using vis_CurvMeshSetParamd and vis_CurvMeshSetParami. In this case a target edge length of .4 is specified with no line element spanning more than 30. degrees. The size of the generated line elements is the minimum of these two size criteria.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble xc[5][3] = { {0.,0.,0.}, {0.,.75,0.}, {.0732233,.9267767,0.}, {.25,1.,0.}, {2.,1.,0.} }; static Vint pc[5] = { 0, 1, 0, 1, 0 }; static Vint lix[4][2] = { {1,2}, {2,3}, {3,4}, {4,5} }; static Vdouble vex[4][2][3] = { {{0.,1.,0.},{0.,1.,0.}}, {{0.,1.,0.},{.707,.707,0.}}, {{.707,.707,0.},{1.,0.,0.}}, {{1.,0.,0.},{1.,0.,0.}} }; /*---------------------------------------------------------------------- Generate a Boundary Mesh ----------------------------------------------------------------------*/ int main() { vis_CurvMesh *curvmesh; vis_Connect *connect; Vint i; Vint numnp, numel; Vdouble x[3]; Vint aid, aid1; Vint nix, ix[3]; /* create CurvMesh object */ curvmesh = vis_CurvMeshBegin (); vis_CurvMeshDef (curvmesh,5,4); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < 5; i++) { vis_CurvMeshSetPoint (curvmesh,i+1,xc[i],pc[i]); } /* define parabolic line segment connectivity */ for (i = 0; i < 4; i++) { vis_CurvMeshSetLine (curvmesh,i+1,lix[i]); vis_CurvMeshSetLineTang (curvmesh,i+1,vex[i]); } /* set assoc of 100 at line 1 */ vis_CurvMeshSetLineAssoc (curvmesh,VIS_MISCID,1,100); /* set assoc of 200 at point 5 */ vis_CurvMeshSetPointAssoc (curvmesh,VIS_MISCID1,5,200); /* set mesh parameters */ vis_CurvMeshSetParami (curvmesh,VIS_MESH_MAXI,3); vis_CurvMeshSetParamd (curvmesh,VIS_MESH_SPANANGLE,30.); vis_CurvMeshSetParamd (curvmesh,VIS_MESH_EDGELENGTH,.4); /* generate */ vis_CurvMeshGenerate (curvmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); vis_ConnectWrite (connect,SYS_SDRC_UNIVERSAL,"exam46.unv"); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d\n", i,ix[0],ix[1],ix[2]); } /* end objects */ vis_ConnectEnd (connect); vis_CurvMeshEnd (curvmesh); return 0; }
The number of input points and the number and order of input triangles are specified by calling vis_SurfMeshDef, then each point and triangle is input using vis_SurfMeshSetPoint and vis_SurfMeshSetTri respectively. In general new points are placed on the surface defined by the triangular facets and any defined point may be moved unless it is explicitly preserved. Note that the four corner input points are marked as preserved in the function vis_SurfMeshSetPoint so that they do not move.
The density of the generated mesh and the order of elements to generate are specified using vis_SurfMeshSetParamd and vis_SurfMeshSetParami. The dimensions of the plate are approximately 1. by 2. and it has been folded in the middle through 90 degrees with a radius of curvature of .1 . A target edge length of .2 is specified with no element spanning more than 30. degrees. The size of the generated elements is the minimum of these two size criteria. A minimum edge length of .02 is specified. This ensures that no unnecessarily small triangles are produced. The call vis_SurfMeshGenerate generates nodes and triangular elements and enters them into the Connect object.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble xc[12][3] = { {0.000e+00, 0.000e+00, 0.000e+00}, {0.000e+00, 9.000e-01, 0.000e+00}, {1.333e-02, 9.500e-01, 0.000e+00}, {5.000e-02, 9.866e-01, 0.000e+00}, {1.000e-01, 1.000e+00, 0.000e+00}, {1.000e+00, 1.000e+00, 0.000e+00}, {0.000e+00, 0.000e+00, 1.000e+00}, {0.000e+00, 9.000e-01, 1.000e+00}, {1.333e-02, 9.500e-01, 1.000e+00}, {5.000e-02, 9.866e-01, 1.000e+00}, {1.000e-01, 1.000e+00, 1.000e+00}, {1.000e+00, 1.000e+00, 1.000e+00} }; static Vint pc[12] = { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1}; static Vint tix[10][3] = { {1, 2, 7}, {2, 8, 7}, {2, 3, 8}, {3, 9, 8}, {3, 4, 9}, {4, 10, 9}, {4, 5, 10}, {5, 11, 10}, {5, 6, 11}, {6, 12, 11} }; static Vint efl[3] = { 0, 0, 0 }; /*---------------------------------------------------------------------- Generate a Surface Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_Connect *connect; Vint i; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[3]; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,12,10); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < 12; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* define triangle connectivity */ for (i = 0; i < 10; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl); } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,30.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.02); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.2); /* write out file encapsulating meshing specifications */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam47.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); printf("id= %d x= %f, y= %f, z= %f\n",i,x[0],x[1],x[2]); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); printf("id= %d ix= %d %d %d\n", i,ix[0],ix[1],ix[2]); } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam47.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
The function vis_SurfMeshSetParami is used to indicate that parabolic triangles are to be output. The mesh density and spanning angle parameters are doubled from those used in Example 47 where linear elements were generated. The call vis_SurfMeshGenerate generates nodes and triangular elements and enters them into the Connect object. The resulting mesh is printed and also written to file exam47a.bdf in NASTRAN bulk data file format. Note that vis/exam/exam30ddev.c may be used to display the generated mesh saved in the file.
In the figure below, triangle and point numbers are displayed along with triangle vertex normals in orange. Preserved edges are black, free edges are red and interior, unpreserved edges are in white.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* point coordinates */ static Vdouble xc[12][3] = { {0.000e+00, 0.000e+00, 0.000e+00}, {0.000e+00, 9.000e-01, 0.000e+00}, {1.333e-02, 9.500e-01, 0.000e+00}, {5.000e-02, 9.866e-01, 0.000e+00}, {1.000e-01, 1.000e+00, 0.000e+00}, {1.000e+00, 1.000e+00, 0.000e+00}, {0.000e+00, 0.000e+00, 1.000e+00}, {0.000e+00, 9.000e-01, 1.000e+00}, {1.333e-02, 9.500e-01, 1.000e+00}, {5.000e-02, 9.866e-01, 1.000e+00}, {1.000e-01, 1.000e+00, 1.000e+00}, {1.000e+00, 1.000e+00, 1.000e+00} }; /* preserved point flags */ static Vint pc[12] = { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1}; /* triangle connectivity */ static Vint tix[10][3] = { {1, 2, 7}, {2, 8, 7}, {2, 3, 8}, {3, 9, 8}, {3, 4, 9}, {4, 10, 9}, {4, 5, 10}, {5, 11, 10}, {5, 6, 11}, {6, 12, 11} }; /* triangle preserved edge flags */ static Vint efl[10][3] = { {0, 0, 0}, {1, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; /* triangle node normals */ static Vdouble tvn[10][3][3] = { {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {.867, -.500, 0.}, { 1., 0., 0.}}, {{.867, -.500, 0.}, {.867, -.500, 0.}, { 1., 0., 0.}}, {{.867, -.500, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}} }; /* triangle associations */ static Vint tpid[10] = { 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 }; /*---------------------------------------------------------------------- Generate a 3D Surface Mesh with Associations ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_Connect *connect; Vint i; Vint numnp, numel; Vdouble x[3]; Vint aid, aid1, pid; Vint nix, ix[6]; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,12,10); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < 12; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* set node associations at points 1 and 7 */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID1,1,1011); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID ,7,1001); /* define triangle connectivity, normals and property id */ for (i = 0; i < 10; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,tvn[i]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,tpid[i]); } /* set node associations at triangle edge */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_EDGE,1,1002); /* set node associations on triangles */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,1,SYS_FACE,0,1003); vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_FACE,0,1003); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,60.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.04); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.4); /* generate */ vis_SurfMeshGenerate (surfmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); vis_ConnectElemAssoc (connect,VIS_PROPID,1,&i,&pid); printf("id= %d ix= %d %d %d %d %d %d, pid= %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5],pid); } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam47a.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
An option is activated to compute normals at the nodes of the final triangle mesh. Use vis_SurfMeshSetParami with parameter VIS_MESH_COMPUTENORMAL to enable this option.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* point coordinates */ static Vdouble xc[14][3] = { {0.000e+00, 0.000e+00, 0.000e+00}, {0.000e+00, 9.000e-01, 0.000e+00}, {1.333e-02, 9.500e-01, 0.000e+00}, {5.000e-02, 9.867e-01, 0.000e+00}, {1.000e-01, 1.000e+00, 0.000e+00}, {1.000e+00, 1.000e+00, 0.000e+00}, {0.000e+00, 0.000e+00, 1.000e+00}, {0.000e+00, 9.000e-01, 1.000e+00}, {1.333e-02, 9.500e-01, 1.000e+00}, {5.000e-02, 9.867e-01, 1.000e+00}, {1.000e-01, 1.000e+00, 1.000e+00}, {1.000e+00, 1.000e+00, 1.000e+00}, {1.500e+00, 9.000e-01, 0.000e+00}, {1.500e+00, 9.000e-01, 1.000e+00} }; /* point preservation flags */ static Vint pc[14] = { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1}; /* triangle connectivity */ static Vint tix[12][3] = { {1, 2, 7}, {2, 8, 7}, {2, 3, 8}, {3, 9, 8}, {3, 4, 9}, {4, 10, 9}, {4, 5, 10}, {5, 11, 10}, {5, 6, 11}, {6, 12, 11}, {6, 13, 12}, {13, 14, 12} }; /* triangle node normals */ static Vdouble tvn[12][3][3] = { {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {.867, -.500, 0.}, {1., 0., 0.}}, {{.867, -.500, 0.}, {.867, -.500, 0.}, {1., 0., 0.}}, {{.867, -.500, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{-.196, -.981, 0.}, {-.196, -.981, 0.}, {-.196, -.981, 0.}}, {{-.196, -.981, 0.}, {-.196, -.981, 0.}, {-.196, -.981, 0.}} }; /* triangle property ids */ static Vint tpid[12] = { 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3 }; /*---------------------------------------------------------------------- Generate a 3D Surface Mesh with Normals and Associations ----------------------------------------------------------------------*/ int main() { vis_Connect *connectgeo; vis_Group *groupface, *groupedge; vis_SurfMesh *surfmesh; vis_Connect *connect; Vint i, k; Vint numpnts, numtris; Vint flags; Vint efl[3]; Vint numnp, numel; Vdouble x[3], ve[6][3]; Vint aid, aid1, pid; Vint nix, ix[6]; numpnts = 14; numtris = 12; /* enter geometry */ connectgeo = vis_ConnectBegin (); vis_ConnectPre (connectgeo,SYS_DOUBLE); vis_ConnectDef (connectgeo,numpnts,numtris); /* enter points */ for (i = 0; i < numpnts; i++) { vis_ConnectSetCoordsdv (connectgeo,i+1,xc[i]); } /* enter triangles */ for (i = 0; i < numtris; i++) { vis_ConnectSetTopology (connectgeo,i+1,VIS_SHAPETRI,2,0,0); vis_ConnectSetElemNode (connectgeo,i+1,tix[i]); vis_ConnectSetElemNormdv (connectgeo,i+1,1,tvn[i]); } vis_ConnectKernel (connectgeo,0); /* determine feature edges */ /* group of faces */ groupface = vis_GroupBegin (); vis_GroupDef (groupface,numtris,SYS_ELEM,SYS_FACE); vis_ConnectFaceGroup (connectgeo,CONNECT_FREE,NULL,groupface); /* extract feature edges and nodes at 10. degrees */ vis_ConnectSetGroupParamf (connectgeo,CONNECT_FEATUREANGLE,10.); vis_ConnectSetGroupParami (connectgeo,CONNECT_FEATURESENSE,VIS_ON); /* curvature changes greater than unity */ vis_ConnectSetGroupParamf (connectgeo,CONNECT_CURVATURECHANGE,1.); /* group of feature edges */ groupedge = vis_GroupBegin (); vis_GroupDef (groupedge,numtris,SYS_ELEM,SYS_EDGE); /* surface discontinuity */ vis_ConnectEdgeGroup (connectgeo,CONNECT_FEATURE,groupface,groupedge); /* curvature discontinuity */ vis_ConnectEdgeGroup (connectgeo,CONNECT_CURVATURE,groupface,groupedge); /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < numpnts; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* set node associations at points */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID1,1,1011); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID ,7,1001); /* define triangle connectivity and property id */ for (i = 0; i < numtris; i++) { for(k = 1; k <= 3; k++) { vis_GroupGetEntFlag (groupedge,i+1,k,&flags); if(flags) { efl[k-1] = 1; } else { efl[k-1] = 0; } } vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl); vis_SurfMeshSetTriNorm (surfmesh,i+1,tvn[i]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,tpid[i]); } /* set node associations at triangle edge */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_EDGE,1,1002); /* set node associations on triangles */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,1,SYS_FACE,0,1003); vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_FACE,0,1003); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParami (surfmesh,VIS_MESH_COMPUTENORMAL,1); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,60.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.04); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.4); /* generate */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam47b.srf"); vis_SurfMeshGenerate (surfmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); /* element connectivity */ vis_ConnectElemAssoc (connect,VIS_PROPID,1,&i,&pid); printf("id= %d ix= %d %d %d %d %d %d, pid= %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5],pid); /* element normals */ vis_ConnectElemNormdv (connect,i,1,ve); for(k = 0; k < nix; k++) { printf(" n= %e %e %e\n",ve[k][0],ve[k][1],ve[k][2]); } } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam47b.bdf"); /* end objects */ vis_ConnectEnd (connectgeo); vis_GroupEnd (groupface); vis_GroupEnd (groupedge); vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* point coordinates */ static Vdouble xc[16][3] = { {0.000e+00, 0.000e+00, 0.000e+00}, {0.000e+00, 9.000e-01, 0.000e+00}, {1.333e-02, 9.500e-01, 0.000e+00}, {5.000e-02, 9.867e-01, 0.000e+00}, {1.000e-01, 1.000e+00, 0.000e+00}, {1.000e+00, 1.000e+00, 0.000e+00}, {0.000e+00, 0.000e+00, 1.000e+00}, {0.000e+00, 9.000e-01, 1.000e+00}, {1.333e-02, 9.500e-01, 1.000e+00}, {5.000e-02, 9.867e-01, 1.000e+00}, {1.000e-01, 1.000e+00, 1.000e+00}, {1.000e+00, 1.000e+00, 1.000e+00}, {1.500e+00, 9.000e-01, 0.000e+00}, {1.500e+00, 9.000e-01, 1.000e+00}, {1.000e+00, 0.000e+00, 0.000e+00}, {1.000e+00, 0.000e+00, 1.000e+00} }; /* point preservation flags */ static Vint pc[16] = { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 }; /* triangle connectivity */ static Vint tix[14][3] = { {1, 2, 7}, {2, 8, 7}, {2, 3, 8}, {3, 9, 8}, {3, 4, 9}, {4, 10, 9}, {4, 5, 10}, {5, 11, 10}, {5, 6, 11}, {6, 12, 11}, {6, 13, 12}, {13, 14, 12}, {12, 15, 6}, {16, 15, 12} }; /* triangle node normals */ static Vdouble tvn[14][3][3] = { {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {.867, -.500, 0.}, {1., 0., 0.}}, {{.867, -.500, 0.}, {.867, -.500, 0.}, {1., 0., 0.}}, {{.867, -.500, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{-.196, -.981, 0.}, {-.196, -.981, 0.}, {-.196, -.981, 0.}}, {{-.196, -.981, 0.}, {-.196, -.981, 0.}, {-.196, -.981, 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}} }; /* triangle property ids */ static Vint tpid[14] = { 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4 }; /*---------------------------------------------------------------------- Generate a Non-Manifold 3D Surface Mesh with Sizing ----------------------------------------------------------------------*/ int main() { vis_Connect *connectgeo; vis_Group *groupface, *groupedge; vis_SurfMesh *surfmesh; vis_Connect *connect; Vint i, k; Vint numpnts, numtris; Vint flags; Vint efl[3]; Vint numnp, numel; Vdouble x[3], ve[6][3]; Vint aid, aid1, pid; Vint nix, ix[6]; numpnts = 16; numtris = 14; /* enter geometry */ connectgeo = vis_ConnectBegin (); vis_ConnectPre (connectgeo,SYS_DOUBLE); vis_ConnectDef (connectgeo,numpnts,numtris); /* enter points */ for (i = 0; i < numpnts; i++) { vis_ConnectSetCoordsdv (connectgeo,i+1,xc[i]); } /* enter triangles */ for (i = 0; i < numtris; i++) { vis_ConnectSetTopology (connectgeo,i+1,VIS_SHAPETRI,2,0,0); vis_ConnectSetElemNode (connectgeo,i+1,tix[i]); vis_ConnectSetElemNormdv (connectgeo,i+1,1,tvn[i]); } vis_ConnectKernel (connectgeo,0); /* determine feature edges */ /* group of faces */ groupface = vis_GroupBegin (); vis_GroupDef (groupface,numtris,SYS_ELEM,SYS_FACE); vis_ConnectFaceGroup (connectgeo,CONNECT_FREE,NULL,groupface); /* extract feature edges and nodes at 10. degrees */ vis_ConnectSetGroupParamf (connectgeo,CONNECT_FEATUREANGLE,10.); vis_ConnectSetGroupParami (connectgeo,CONNECT_FEATURESENSE,VIS_ON); /* curvature changes greater than unity */ vis_ConnectSetGroupParamf (connectgeo,CONNECT_CURVATURECHANGE,1.); /* group of feature edges */ groupedge = vis_GroupBegin (); vis_GroupDef (groupedge,numtris,SYS_ELEM,SYS_EDGE); /* surface discontinuity */ vis_ConnectEdgeGroup (connectgeo,CONNECT_FEATURE,groupface,groupedge); /* curvature discontinuity */ vis_ConnectEdgeGroup (connectgeo,CONNECT_CURVATURE,groupface,groupedge); /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < numpnts; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* set node associations at points */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID1,1,1011); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID ,7,1001); /* define triangle connectivity and property id */ for (i = 0; i < numtris; i++) { for(k = 1; k <= 3; k++) { vis_GroupGetEntFlag (groupedge,i+1,k,&flags); if(flags) { efl[k-1] = 1; } else { efl[k-1] = 0; } } vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl); vis_SurfMeshSetTriNorm (surfmesh,i+1,tvn[i]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,tpid[i]); /* specific sizing for region 3 */ if(tpid[i] == 3) { vis_SurfMeshSetTriSizing (surfmesh,i+1,SYS_FACE,0,.05); } if((i+1) == 12) { vis_SurfMeshSetTriSizing (surfmesh,i+1,SYS_EDGE,1,.0125); } } /* set node associations at triangle edge */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_EDGE,1,1002); /* set node associations on triangles */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,1,SYS_FACE,0,1003); vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,2,SYS_FACE,0,1003); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParami (surfmesh,VIS_MESH_COMPUTENORMAL,1); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,60.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.04); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.4); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam47c.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); /* element connectivity */ vis_ConnectElemAssoc (connect,VIS_PROPID,1,&i,&pid); printf("id= %d ix= %d %d %d %d %d %d, pid= %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5],pid); /* element normals */ vis_ConnectElemNormdv (connect,i,1,ve); for(k = 0; k < nix; k++) { printf(" n= %e %e %e\n",ve[k][0],ve[k][1],ve[k][2]); } } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam47c.bdf"); /* end objects */ vis_ConnectEnd (connectgeo); vis_GroupEnd (groupface); vis_GroupEnd (groupedge); vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* point coordinates */ static Vdouble xc[20][3] = { {0.000e+00, 0.000e+00, 0.000e+00}, {0.000e+00, 9.000e-01, 0.000e+00}, {1.333e-02, 9.500e-01, 0.000e+00}, {5.000e-02, 9.867e-01, 0.000e+00}, {1.000e-01, 1.000e+00, 0.000e+00}, {1.000e+00, 1.000e+00, 0.000e+00}, {0.000e+00, 0.000e+00, 1.000e+00}, {0.000e+00, 9.000e-01, 1.000e+00}, {1.333e-02, 9.500e-01, 1.000e+00}, {5.000e-02, 9.867e-01, 1.000e+00}, {1.000e-01, 1.000e+00, 1.000e+00}, {1.000e+00, 1.000e+00, 1.000e+00}, {1.500e+00, 9.000e-01, 0.000e+00}, {1.500e+00, 9.000e-01, 1.000e+00}, {1.000e+00, 0.000e+00, 0.000e+00}, {1.000e+00, 0.000e+00, 1.000e+00}, {1.0, .33, .66}, {1.0, .33, .33}, {1.0, .66, .33}, {1.0, .66, .66} }; /* point preservation flags */ static Vint pc[20] = { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }; /* triangle connectivity */ static Vint tix[14][3] = { {1, 2, 7}, {2, 8, 7}, {2, 3, 8}, {3, 9, 8}, {3, 4, 9}, {4, 10, 9}, {4, 5, 10}, {5, 11, 10}, {5, 6, 11}, {6, 12, 11}, {6, 13, 12}, {13, 14, 12}, {12, 15, 6}, {16, 15, 12} }; /* triangle node normals */ static Vdouble tvn[14][3][3] = { {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {.867, -.500, 0.}, {1., 0., 0.}}, {{.867, -.500, 0.}, {.867, -.500, 0.}, {1., 0., 0.}}, {{.867, -.500, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {.500, -.867, 0.}, {.867, -.500, 0.}}, {{.500, -.867, 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {.500, -.867, 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{0., -1., 0.}, {0., -1., 0.}, {0., -1., 0.}}, {{-.196, -.981, 0.}, {-.196, -.981, 0.}, {-.196, -.981, 0.}}, {{-.196, -.981, 0.}, {-.196, -.981, 0.}, {-.196, -.981, 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}}, {{1., 0., 0.}, {1., 0., 0.}, {1., 0., 0.}} }; /* triangle property ids */ static Vint tpid[14] = { 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4 }; /*---------------------------------------------------------------------- Generate a 3D Surface Mesh with Trimming Loop ----------------------------------------------------------------------*/ int main() { vis_Connect *connectgeo; vis_Group *groupface, *groupedge; vis_SurfMesh *surfmesh; vis_Connect *connect; Vint i, k; Vint numpnts, numtris; Vint flags; Vint efl[3]; Vint numnp, numel; Vdouble x[3], ve[6][3]; Vint aid, aid1, pid; Vint nix, ix[6]; Vint eix[5]; numpnts = 20; numtris = 14; /* enter geometry */ connectgeo = vis_ConnectBegin (); vis_ConnectPre (connectgeo,SYS_DOUBLE); vis_ConnectDef (connectgeo,numpnts,numtris); /* enter points */ for (i = 0; i < numpnts; i++) { vis_ConnectSetCoordsdv (connectgeo,i+1,xc[i]); } /* enter triangles */ for (i = 0; i < numtris; i++) { vis_ConnectSetTopology (connectgeo,i+1,VIS_SHAPETRI,2,0,0); vis_ConnectSetElemNode (connectgeo,i+1,tix[i]); vis_ConnectSetElemNormdv (connectgeo,i+1,1,tvn[i]); } vis_ConnectKernel (connectgeo,0); /* determine feature edges */ /* group of faces */ groupface = vis_GroupBegin (); vis_GroupDef (groupface,numtris,SYS_ELEM,SYS_FACE); vis_ConnectFaceGroup (connectgeo,CONNECT_FREE,NULL,groupface); /* extract feature edges and nodes at 10. degrees */ vis_ConnectSetGroupParamf (connectgeo,CONNECT_FEATUREANGLE,10.); vis_ConnectSetGroupParami (connectgeo,CONNECT_FEATURESENSE,VIS_ON); /* curvature changes greater than unity */ vis_ConnectSetGroupParamf (connectgeo,CONNECT_CURVATURECHANGE,1.); /* group of feature edges */ groupedge = vis_GroupBegin (); vis_GroupDef (groupedge,numtris,SYS_ELEM,SYS_EDGE); /* surface discontinuity */ vis_ConnectEdgeGroup (connectgeo,CONNECT_FEATURE,groupface,groupedge); /* curvature discontinuity */ vis_ConnectEdgeGroup (connectgeo,CONNECT_CURVATURE,groupface,groupedge); /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < numpnts; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* set node associations at points */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID1,1,1011); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID ,7,1001); /* define triangle connectivity and property id */ for (i = 0; i < numtris; i++) { for(k = 1; k <= 3; k++) { vis_GroupGetEntFlag (groupedge,i+1,k,&flags); if(flags) { efl[k-1] = 1; } else { efl[k-1] = 0; } } vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl); vis_SurfMeshSetTriNorm (surfmesh,i+1,tvn[i]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,tpid[i]); /* specific sizing for region 3 */ if(tpid[i] == 3) { vis_SurfMeshSetTriSizing (surfmesh,i+1,SYS_FACE,0,.05); } if((i+1) == 12) { vis_SurfMeshSetTriSizing (surfmesh,i+1,SYS_EDGE,1,.0125); } } /* set trimming loop */ eix[0] = 20; eix[1] = 19; eix[2] = 18; eix[3] = 17; eix[4] = 20; vis_SurfMeshSetEdge (surfmesh,VIS_ON,5,eix,VIS_OFF,NULL); /* set node associations at triangle edge */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_EDGE,1,1002); /* set node associations on triangles */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,1,SYS_FACE,0,1003); vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID,2,SYS_FACE,0,1003); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParami (surfmesh,VIS_MESH_COMPUTENORMAL,1); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,60.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.04); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.4); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam47d.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); vis_ConnectNodeAssoc (connect,VIS_MISCID1,1,&i,&aid1); printf("id= %d x= %f, y= %f, z= %f, aid= %d, aid1= %d\n", i,x[0],x[1],x[2],aid,aid1); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); /* element connectivity */ vis_ConnectElemAssoc (connect,VIS_PROPID,1,&i,&pid); printf("id= %d ix= %d %d %d %d %d %d, pid= %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5],pid); /* element normals */ vis_ConnectElemNormdv (connect,i,1,ve); for(k = 0; k < nix; k++) { printf(" n= %e %e %e\n",ve[k][0],ve[k][1],ve[k][2]); } } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam47d.bdf"); /* end objects */ vis_ConnectEnd (connectgeo); vis_GroupEnd (groupface); vis_GroupEnd (groupedge); vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
The STL file is read using the convenience function vis_ConnectRead in the Connect object. The initial triangles are unconnected so vis_ConnectMerge is called to merge coincident nodes together. Feature edges and nodes are identified using standard Connect object functions. These feature edges and nodes will be flagged to be "preserved" in the surface meshing phase. The target edge length is set to be about 5 percent of the model extent. The surface mesh is generated using vis_SurfMeshGenerate. The resulting surface mesh is input to the TetMesh module and the tetrahedral mesh is generated using vis_TetMeshGenerate. The final mesh is output to a SDRC Universal file using the convenience function vis_ConnectWrite.
#include <math.h> #include <stdio.h> #include <stdlib.h> #include "base/base.h" #include "vis/vismesh.h" /* useful macro for parsing group activity flags */ #define VIEW_FLAG(flags,ind) (((flags) >> ((ind)-1)) & 1) /*---------------------------------------------------------------------- Generate a 3D Volume Tet Mesh from an STL or OBJ File ----------------------------------------------------------------------*/ int main(int argc, char **argv) { Vint i, k; vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connect, *connectsurf, *connecttet; vis_Group *groupface, *groupedge, *groupnode; Vint numpnts, numtris; Vdouble x[3]; Vint nix, tri[3], edgeflags[3]; Vint numsurfpnts, numsurftris; Vint numtetpnts, numtets; Vint flags; Vdouble edgelen; Vfloat bbox[2][3]; Vdouble d[3], fl; Vchar inpath[256], outpath[256]; Vint filetype; /* check for proper number of arguments */ if(argc < 2) { fprintf(stderr,"Usage: %s inputfile outputfile\n",argv[0]); fprintf(stderr," inputfile is blank, 'angle.stl' is assumed\n"); strcpy(inpath,"angle.stl"); } else { strcpy(inpath,argv[1]); } if(argc < 3) { fprintf(stderr,"Usage: %s inputfile outputfile\n",argv[0]); fprintf(stderr," outputfile is blank, 'exam48.unv' is assumed\n"); strcpy(outpath,"exam48.unv"); } else { strcpy(outpath,argv[2]); } /* detect file type */ if(strstr(inpath,".stl") != NULL || strstr(inpath,".STL") != NULL) { filetype = SYS_FILE_STL; } else if(strstr(inpath,".obj") != NULL) { filetype = SYS_FILE_OBJ; } else { fprintf(stderr,"Unrecognized file type, file: %s\n",inpath); exit(0); } /* instance Connect object to hold STL or OBJ data */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); vis_ConnectRead (connect,filetype,inpath); if(filetype == SYS_FILE_STL) { printf("Read STL file complete\n"); } else { printf("Read OBJ file complete\n"); } /* determine model extent for element sizing */ vis_ConnectExtent (connect,NULL,bbox); d[0] = bbox[1][0] - bbox[0][0]; d[1] = bbox[1][1] - bbox[0][1]; d[2] = bbox[1][2] - bbox[0][2]; fl = sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]); /* merge disconnected triangles in STL file together */ if(filetype == SYS_FILE_STL) { vis_ConnectSetParamf (connect,CONNECT_TOLERANCE,.00001*fl); vis_ConnectMerge (connect,NULL); } vis_ConnectNumber (connect,SYS_NODE,&numpnts); vis_ConnectNumber (connect,SYS_ELEM,&numtris); /* determine feature edges, etc. */ vis_ConnectKernel (connect,0); /* group of faces */ groupface = vis_GroupBegin (); vis_GroupDef (groupface,numtris,SYS_ELEM,SYS_FACE); vis_ConnectFaceGroup (connect,CONNECT_FREE,NULL,groupface); /* extract feature edges and nodes at 45. degrees */ vis_ConnectSetGroupParamf (connect,CONNECT_FEATUREANGLE,45.); vis_ConnectSetGroupParami (connect,CONNECT_FEATURESENSE,VIS_ON); /* group of feature edges */ groupedge = vis_GroupBegin (); vis_GroupDef (groupedge,numtris,SYS_ELEM,SYS_EDGE); vis_ConnectEdgeGroup (connect,CONNECT_FEATURE,groupface,groupedge); /* group of feature nodes */ groupnode = vis_GroupBegin (); vis_GroupDef (groupnode,numpnts,SYS_NODE,SYS_NONE); vis_ConnectNodeGroup (connect,CONNECT_FEATURE,groupedge,groupnode); /* instance surf mesher */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* define input points with feature points preserved */ for(i = 1; i <= numpnts; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_GroupGetIndex (groupnode,i,&flags); vis_SurfMeshSetPoint (surfmesh,i,x,flags); } /* define input triangles with feature edges preserved */ for(i = 1; i <= numtris; i++) { vis_ConnectElemNode (connect,i,&nix,tri); vis_GroupGetIndex (groupedge,i,&flags); for(k = 1; k <= 3; k++) { if(VIEW_FLAG(flags,k)) { edgeflags[k-1] = 1; } else { edgeflags[k-1] = 0; } } vis_SurfMeshSetTri (surfmesh,i,tri,edgeflags); } /* instance Connect object to hold generated surface tris */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* set target edge length at 5 percent of model extent */ edgelen = .05 * fl; vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelen); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.4*edgelen); /* set span angles, etc. */ vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,30.); vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam48.srf"); /* generate quality surface mesh */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surface mesh generation error\n"); } else { printf("surface mesh generation complete\n"); } /* find out the number of generated nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,2); /* Fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* Fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,tri); vis_TetMeshSetTri (tetmesh,i,tri); } /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,edgelen); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); } else { printf("tet mesh generation complete\n"); } /* write out to Universal file */ vis_ConnectWrite (connecttet,SYS_SDRC_UNIVERSAL,outpath); printf("Write Universal file complete\n"); /* find out the number of generated nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numtetpnts); vis_ConnectNumber (connecttet,SYS_ELEM,&numtets); printf(" Number of nodes= %d\n",numtetpnts); printf(" Number of tets = %d\n",numtets); /* delete objects */ vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); vis_ConnectEnd (connectsurf); vis_ConnectEnd (connecttet); vis_TetMeshEnd (tetmesh); vis_GroupEnd (groupface); vis_GroupEnd (groupedge); vis_GroupEnd (groupnode); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* a simple unit cube */ static Vdouble xc[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint tefl[12][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; static Vdouble norms[12][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /* isotropic size function */ static void s_iso(vis_SurfMesh *surfmesh, Vobject *usrobj, Vdouble x[3], Vdouble *s) { /* linear size gradation in x direction */ *s = .02 + .2*x[0]; } /* anisotropic size function */ static void s_aniso(vis_SurfMesh *surfmesh, Vobject *usrobj, Vdouble x[3], Vdouble s[3][3]) { Vdouble s1, s2, s3; /* 4 to 1 aspect ratio at 45 degree angle in x,y */ s1 = .025; s[0][0] = s1*.707; s[0][1] = s1*.707; s[0][2] = 0.; s2 = .1; s[1][0] = s2*-.707; s[1][1] = s2*.707; s[1][2] = 0.; /* z */ s3 = .2; s[2][0] = 0.; s[2][1] = 0.; s[2][2] = s3*1.; } /*---------------------------------------------------------------------- Generate an Anisotropic Surface Mesh and Tet Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connecttet; Vint i; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[3]; Vint iso; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,8,12); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 8; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 12; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); /* set iso to 1 for isotropic, 0 for anisotropic */ iso = 1; /* set isotropic sizing function */ if(iso) { vis_SurfMeshSetFunction (surfmesh,SYS_FUNCTION_SIZING, (Vfunc*)s_iso,NULL); /* set anisotropic sizing function */ } else { vis_SurfMeshSetFunction (surfmesh,SYS_FUNCTION_ASIZING, (Vfunc*)s_aniso,NULL); } /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam48a_srf.bdf"); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,2); /* Fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* Fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_TetMeshSetTri (tetmesh,i,ix); } /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* set isotropic sizing function */ if(iso) { vis_TetMeshSetFunction (tetmesh,SYS_FUNCTION_SIZING, (Vfunc*)s_iso,NULL); /* set anisotropic sizing function */ } else { vis_TetMeshSetFunction (tetmesh,SYS_FUNCTION_ASIZING, (Vfunc*)s_aniso,NULL); } /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam48a_tet.bdf"); /* end objects */ vis_ConnectEnd (connectsurf); vis_ConnectEnd (connecttet); vis_SurfMeshEnd (surfmesh); vis_TetMeshEnd (tetmesh); return 0; }
The SurfMesh module is used to perform the initial triangulation of the surfaces representing the solid. Non-manifold input support must be enabled in the SurfMesh module using the SURFMESH_NONMANIFOLD parameter in the function vis_SurfMeshSetParami. Since the resulting triangulation is to be input to the TetMesh module for subsequent solid meshing, all internal boundary triangles must be "double backed". This feature is enabled using the SURFMESH_INTSURFBACK parameter. In this case the SurfMesh module will double back the internal face which divides the solid as well as the faces enclosing the inclusion.
Element associations are assigned to all triangles on a face bordering the first region so that the VIS_PROPID association value of 1 will be assigned to all generated tetrahedra enclosed by the face and all other boundary faces. A VIS_PROPID association value of 2 is assigned to all triangles on a face bordering the second region. This will result in all generated tetrahedra within this region to be assigned this value. Note however that the tetrahedra generated within the inclusion are not considered to be in the second region. Finally, a VIS_PROPID of 3 is specified for the inclusion.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* a cube with interior surface, a hole and an inclusion */ static Vdouble xc[28][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,0.,2.}, {1.,0.,2.}, {0.,1.,2.}, {1.,1.,2.}, /* hole */ {.1,.1,.1}, {.2,.1,.1}, {.1,.2,.1}, {.2,.2,.1}, {.1,.1,.2}, {.2,.1,.2}, {.1,.2,.2}, {.2,.2,.2}, /* inclusion */ {.1,.1,1.1}, {.2,.1,1.1}, {.1,.2,1.1}, {.2,.2,1.1}, {.1,.1,1.2}, {.2,.1,1.2}, {.1,.2,1.2}, {.2,.2,1.2} }; static Vint tris[46][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,9,7}, {7,9,11}, {8,10,6}, {12,10,8}, {5,6,9}, {9,6,10}, {11,8,7}, {12,8,11}, {9,12,11}, {9,10,12}, /* hole */ {13,15,17}, {15,19,17}, {16,14,18}, {20,16,18}, {13,17,14}, {17,18,14}, {19,15,16}, {20,19,16}, {13,14,16}, {16,15,13}, {17,19,20}, {17,20,18}, /* inclusion */ {21,25,23}, {23,25,27}, {24,26,22}, {28,26,24}, {21,22,25}, {25,22,26}, {27,24,23}, {28,24,27}, {21,24,22}, {24,21,23}, {25,28,27}, {25,26,28} }; static Vint tefl[46][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {1,1,0}, /* hole */ {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,1,0}, {1,1,0}, {1,1,0}, {0,1,1}, /* inclusion */ {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; static Vdouble norms[46][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, /* hole */ {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, /* inclusion */ {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Surface Mesh and Tet Mesh, Non-manifold Solid ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connecttet; Vint i; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[3], aid; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,28,46); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 28; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 46; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); } /* set property association for each body */ /* set all elements on a face bordering body */ /* body 1 */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,1,SYS_ELEM,0,1); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,2,SYS_ELEM,0,1); /* body 2 */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,21,SYS_ELEM,0,2); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,22,SYS_ELEM,0,2); /* body 3, inclusion */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,45,SYS_ELEM,0,3); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,46,SYS_ELEM,0,3); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,1.); /* write out file encapsulating meshing specifications */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam48b.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } vis_SurfMeshEnd (surfmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam48b-srf.bdf"); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,2); /* Fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* Fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_TetMeshSetTri (tetmesh,i,ix); vis_ConnectElemAssoc (connectsurf,VIS_PROPID,1,&i,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_PROPID,i,SYS_ELEM,0,aid); } } vis_ConnectEnd (connectsurf); /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* write out file encapsulating meshing specifications */ vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam48b.tet"); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } vis_TetMeshEnd (tetmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam48b-tet.bdf"); vis_ConnectEnd (connecttet); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vis.h" #include "vis/vismesh.h" /* a cube with interior surface, a hole and an inclusion */ static Vdouble xc[28][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,0.,2.}, {1.,0.,2.}, {0.,1.,2.}, {1.,1.,2.}, /* hole */ {.1,.1,.1}, {.2,.1,.1}, {.1,.2,.1}, {.2,.2,.1}, {.1,.1,.2}, {.2,.1,.2}, {.1,.2,.2}, {.2,.2,.2}, /* inclusion */ {.1,.1,1.1}, {.2,.1,1.1}, {.1,.2,1.1}, {.2,.2,1.1}, {.1,.1,1.2}, {.2,.1,1.2}, {.1,.2,1.2}, {.2,.2,1.2} }; static Vint tris[46][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,9,7}, {7,9,11}, {8,10,6}, {12,10,8}, {5,6,9}, {9,6,10}, {11,8,7}, {12,8,11}, {9,12,11}, {9,10,12}, /* hole */ {13,15,17}, {15,19,17}, {16,14,18}, {20,16,18}, {13,17,14}, {17,18,14}, {19,15,16}, {20,19,16}, {13,14,16}, {16,15,13}, {17,19,20}, {17,20,18}, /* inclusion */ {21,25,23}, {23,25,27}, {24,26,22}, {28,26,24}, {21,22,25}, {25,22,26}, {27,24,23}, {28,24,27}, {21,24,22}, {24,21,23}, {25,28,27}, {25,26,28} }; static Vint tefl[46][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {1,1,0}, /* hole */ {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,1,0}, {1,1,0}, {1,1,0}, {0,1,1}, /* inclusion */ {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; static Vdouble norms[46][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, /* hole */ {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, /* inclusion */ {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Surface Mesh and Tet Mesh, Non-manifold Solid ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connecttet, *connectref; vis_State *state; vis_GridFun *gf; Vint i, j; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3], size; Vint nix, ix[3], aid; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,28,46); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 28; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 46; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); for(j = 0; j < 3; j++) { if(tefl[i][j]) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1,1); } } vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); } /* set property association for each body */ /* set all elements on a face bordering body */ /* body 1 */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,1,SYS_ELEM,0,1); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,2,SYS_ELEM,0,1); /* body 2 */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,21,SYS_ELEM,0,2); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,22,SYS_ELEM,0,2); /* body 3, inclusion */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,45,SYS_ELEM,0,3); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,46,SYS_ELEM,0,3); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,1.); /* write out file encapsulating meshing specifications */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam48c.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } vis_SurfMeshEnd (surfmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam48c-srf.bdf"); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,2); /* Fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* Fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_TetMeshSetTri (tetmesh,i,ix); vis_ConnectElemAssoc (connectsurf,VIS_PROPID,1,&i,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_PROPID,i,SYS_ELEM,0,aid); } /* flag preserved edge with a VIS_GEOEDGE association */ for(j = 1; j <= 3; j++) { vis_ConnectElemEntAssoc (connectsurf,VIS_GEOEDGE,SYS_EDGE,i,j,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_PROPID,i,SYS_EDGE,j,aid); } } } vis_ConnectEnd (connectsurf); /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* write out file encapsulating meshing specifications */ vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam48c.tet"); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam48c-tet.bdf"); /* refine mesh */ state = vis_StateBegin (); gf = vis_GridFunBegin (); vis_ConnectGridFun (connecttet,gf); vis_StateSetObject (state,VIS_GRIDFUN,(Vobject*)gf); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); for(i = 1; i <= numel; i++) { size = .125; vis_StateSetDatadv (state,i,&size); } /* refine tetmesh */ connectref = vis_ConnectBegin (); vis_ConnectPre (connectref,SYS_DOUBLE); vis_TetMeshRefine (tetmesh,state,connectref); if(vis_TetMeshError (tetmesh)) { printf("tet mesh refinement error\n"); exit(1); } else { printf("tet mesh refinement complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectref,SYS_NODE,&numnp); vis_ConnectNumber (connectref,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write refined tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectref,SYS_NASTRAN_BULKDATA,"exam48c-ref.bdf"); vis_TetMeshEnd (tetmesh); vis_ConnectEnd (connecttet); vis_ConnectEnd (connectref); vis_StateEnd (state); vis_GridFunEnd (gf); return 0; }
In this example, the hole which existed in Example 48b due to the orientation of the bounding triangles is now defined as a material region using vis_SurfMeshSetTriBack.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* a cube with interior surface, and two inclusions */ /* point coordinates */ static Vdouble xc[28][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,0.,2.}, {1.,0.,2.}, {0.,1.,2.}, {1.,1.,2.}, /* inclusion 1 */ {.1,.1,.1}, {.2,.1,.1}, {.1,.2,.1}, {.2,.2,.1}, {.1,.1,.2}, {.2,.1,.2}, {.1,.2,.2}, {.2,.2,.2}, /* inclusion 2 */ {.1,.1,1.1}, {.2,.1,1.1}, {.1,.2,1.1}, {.2,.2,1.1}, {.1,.1,1.2}, {.2,.1,1.2}, {.1,.2,1.2}, {.2,.2,1.2} }; /* triangle connectivity */ static Vint tris[46][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,9,7}, {7,9,11}, {8,10,6}, {12,10,8}, {5,6,9}, {9,6,10}, {11,8,7}, {12,8,11}, {9,12,11}, {9,10,12}, /* inclusion 1 */ {13,15,17}, {15,19,17}, {16,14,18}, {20,16,18}, {13,17,14}, {17,18,14}, {19,15,16}, {20,19,16}, {13,14,16}, {16,15,13}, {17,19,20}, {17,20,18}, /* inclusion 2 */ {21,25,23}, {23,25,27}, {24,26,22}, {28,26,24}, {21,22,25}, {25,22,26}, {27,24,23}, {28,24,27}, {21,24,22}, {24,21,23}, {25,28,27}, {25,26,28} }; /* triangle right and left element associations */ static Vint ta[46][2] = { /* outer boundary and non-manifold internal surface */ {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,2}, {1,2}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, /* inclusion 1, faces point into inclusion */ {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, /* inclusion 2, faces point out of inclusion */ {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2} }; /* triangle edge flags */ static Vint tefl[46][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {1,1,0}, /* inclusion 1 */ {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,1,0}, {1,1,0}, {1,1,0}, {0,1,1}, /* inclusion 2 */ {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; /* triangle normals */ static Vdouble norms[46][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, /* inclusion 1 */ {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, /* inclusion 2 */ {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Tet Mesh, Non-manifold Solid ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connecttet; Vint i; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[3], aid; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,28,46); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 28; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 46; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); vis_SurfMeshSetTriBack (surfmesh,i+1,ta[i][0],ta[i][1]); /* set property associations */ if(ta[i][0]) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,0,ta[i][0]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,ta[i][0]); } if(ta[i][1]) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,-1,ta[i][1]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,i+1,SYS_ELEM,-1,ta[i][1]); } } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,1.); /* write out file encapsulating meshing specifications */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam48d.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } vis_SurfMeshEnd (surfmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam48d-srf.bdf"); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,2); /* Fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* Fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_TetMeshSetTri (tetmesh,i,ix); vis_ConnectElemAssoc (connectsurf,VIS_PROPID,1,&i,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_PROPID,i,SYS_ELEM,0,aid); } vis_ConnectElemAssoc (connectsurf,VIS_GEOBODY,1,&i,&aid); if(aid) { vis_TetMeshSetTriAssoc (tetmesh,VIS_GEOBODY,i,SYS_ELEM,0,aid); } } vis_ConnectEnd (connectsurf); /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* write out file encapsulating meshing specifications */ vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam48d.tet"); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } vis_TetMeshEnd (tetmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated tet mesh in NASTRAN bulk data format */ vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam48d-tet.bdf"); vis_ConnectEnd (connecttet); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* a cube with interior surface, and two inclusions */ /* point coordinates */ static Vdouble xc[28][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,0.,2.}, {1.,0.,2.}, {0.,1.,2.}, {1.,1.,2.}, /* inclusion 1 */ {.1,.1,.1}, {.2,.1,.1}, {.1,.2,.1}, {.2,.2,.1}, {.1,.1,.2}, {.2,.1,.2}, {.1,.2,.2}, {.2,.2,.2}, /* inclusion 2 */ {.1,.1,1.1}, {.2,.1,1.1}, {.1,.2,1.1}, {.2,.2,1.1}, {.1,.1,1.2}, {.2,.1,1.2}, {.1,.2,1.2}, {.2,.2,1.2} }; /* triangle connectivity */ static Vint tris[46][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,9,7}, {7,9,11}, {8,10,6}, {12,10,8}, {5,6,9}, {9,6,10}, {11,8,7}, {12,8,11}, {9,12,11}, {9,10,12}, /* inclusion 1 */ {13,15,17}, {15,19,17}, {16,14,18}, {20,16,18}, {13,17,14}, {17,18,14}, {19,15,16}, {20,19,16}, {13,14,16}, {16,15,13}, {17,19,20}, {17,20,18}, /* inclusion 2 */ {21,25,23}, {23,25,27}, {24,26,22}, {28,26,24}, {21,22,25}, {25,22,26}, {27,24,23}, {28,24,27}, {21,24,22}, {24,21,23}, {25,28,27}, {25,26,28} }; /* triangle right and left element associations */ static Vint ta[46][2] = { /* outer boundary and non-manifold internal surface */ {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,2}, {1,2}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, /* inclusion 1, faces point into inclusion */ {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, {1,3}, /* inclusion 2, faces point out of inclusion */ {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2}, {4,2} }; /* triangle edge flags */ static Vint tefl[46][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {1,1,0}, /* inclusion 1 */ {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,0,1}, {1,1,0}, {1,1,0}, {1,0,1}, {1,1,0}, {1,1,0}, {1,1,0}, {0,1,1}, /* inclusion 2 */ {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; /* triangle normals */ static Vdouble norms[46][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, /* inclusion 1 */ {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, /* inclusion 2 */ {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Hybrid Boundary and Volumetric Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_VolMesh *volmesh; vis_Connect *connectsurf, *connectvol; Vint i; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vint aid; Vdouble edgelength; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,28,46); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for(i = 0; i < 28; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for(i = 0; i < 46; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); vis_SurfMeshSetTriBack (surfmesh,i+1,ta[i][0],ta[i][1]); /* set property associations */ if(ta[i][0]) { vis_SurfMeshSetTriAssoc(surfmesh,VIS_PROPID,i+1,SYS_ELEM,0,ta[i][0]); vis_SurfMeshSetTriAssoc(surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,0,ta[i][0]); } if(ta[i][1]) { vis_SurfMeshSetTriAssoc(surfmesh,VIS_PROPID,i+1,SYS_ELEM,-1,ta[i][1]); vis_SurfMeshSetTriAssoc(surfmesh,VIS_GEOBODY,i+1,SYS_ELEM,-1,ta[i][1]); } } /* set mesh parameters */ edgelength = .5; vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,VIS_ON); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelength); /* write out file encapsulating meshing specifications */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam48e.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } vis_SurfMeshEnd (surfmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam48e-srf.bdf"); /* create VolMesh object */ volmesh = vis_VolMeshBegin (); vis_VolMeshDef (volmesh,numsurfpnts,numsurftris); /* Fill VolMesh object with generated surface mesh */ vis_VolMeshConnect (volmesh,connectsurf); /* Define fill regions */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemAssoc (connectsurf,VIS_GEOBODY,1,&i,&aid); /* tet fill for regions 1 and 2 */ if(aid == 1 || aid == 2) { vis_VolMeshSetFaceFill (volmesh,i,VOLMESH_FILL_TET); /* boundary output for regions 3 and 4 */ } else { vis_VolMeshSetFaceFill (volmesh,i,VOLMESH_FILL_BOUNDARY); } } vis_VolMeshSetParamd (volmesh,VIS_MESH_EDGELENGTH,edgelength); vis_ConnectEnd (connectsurf); /* create Connect object to hold generated vol mesh */ connectvol = vis_ConnectBegin (); vis_ConnectPre (connectvol,SYS_DOUBLE); vis_ConnectDef (connectvol,0,0); /* write out file encapsulating meshing specifications */ vis_VolMeshWrite (volmesh,SYS_ASCII,"exam48e.vol"); /* generate mesh */ vis_VolMeshGenerate (volmesh,connectvol); if(vis_VolMeshError (volmesh)) { printf("hybrid mesh generation error\n"); exit(1); } else { printf("hybrid mesh generation complete\n"); } vis_VolMeshEnd (volmesh); /* print number of surface nodes and elements */ vis_ConnectNumber (connectvol,SYS_NODE,&numnp); vis_ConnectNumber (connectvol,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated hybrid mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectvol,SYS_NASTRAN_BULKDATA,"exam48e-vol.bdf"); vis_ConnectEnd (connectvol); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" #include "base/system.h" /* a simple unit cube */ static Vdouble xc[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint tefl[12][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; static Vdouble norms[12][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Surface Mesh and Pyr/Tet Mesh Interior Sizing ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_VolMesh *volmesh; vis_Connect *connectsurf, *connectvol; Vint i; Vint numsurfpnts, numsurftris; Vint numnp, numel; Vdouble x[3]; Vint nix, ix[4]; Vdouble isize, bsize; Vdouble xo[3], xa[3], xb[3], d[3]; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,8,12); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 8; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 12; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,2); vis_SurfMeshSetParami (surfmesh,VIS_MESH_SHAPE,VIS_SHAPEQUAD); /* boundary size */ bsize = .05; vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,bsize); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* create VolMesh object */ volmesh = vis_VolMeshBegin (); vis_VolMeshDef (volmesh,numsurfpnts,numsurftris); /* interior ellipsoidal shape for sizing */ /* positioned in center of cube */ xo[0] = .5; xo[1] = .5; xo[2] = .5; /* oriented along x axis and at 45 degrees in y-z plane */ xa[0] = 1.0; xa[1] = .5; xa[2] = .5; xb[0] = .5; xb[1] = 1.0; xb[2] = 1.0; /* lengths of ellipsoid along each axis */ d[0] = .10; d[1] = .20; d[2] = .30; vis_VolMeshSetGeomSizing (volmesh,VIS_MESH_GEOMSPHERE,xo,xa,xb,d,0.02); /* interior sizing */ isize = .2; vis_VolMeshSetParamd (volmesh,VIS_MESH_EDGELENGTH,isize); /* Fill VolMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_VolMeshSetNode (volmesh,i,x); } /* Fill VolMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,ix); vis_VolMeshSetFace (volmesh,i,VIS_SHAPEQUAD,0,0,ix); } /* set boundary depth and size */ for(i = 1; i <= numsurftris; i++) { vis_VolMeshSetFaceDepthSizing (volmesh,i,0.1,bsize); } /* create Connect object to hold generated pyr/tet mesh */ connectvol = vis_ConnectBegin (); vis_ConnectPre (connectvol,SYS_DOUBLE); vis_ConnectDef (connectvol,0,0); vis_VolMeshWrite (volmesh,SYS_ASCII,"exam48f.vol"); /* generate mesh */ vis_VolMeshGenerate (volmesh,connectvol); if(vis_VolMeshError (volmesh)) { printf("Vol mesh generation error\n"); exit(1); } else { printf("Vol mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectvol,SYS_NODE,&numnp); vis_ConnectNumber (connectvol,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectvol,SYS_NASTRAN_BULKDATA,"exam48f.bdf"); /* end objects */ vis_ConnectEnd (connectsurf); vis_ConnectEnd (connectvol); vis_SurfMeshEnd (surfmesh); vis_VolMeshEnd (volmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* a unit cube and interior edge endpoints */ static Vdouble xc[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}}; static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; static Vint tefl[12][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0} }; static Vdouble norms[12][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; static Vdouble xe[2][3] = { {0.25,0.25,0.25}, {0.75,0.75,0.25}}; static Vint lin[2] = {1,2}; static Vdouble tangs[2][3] = { {1.,0.,0.}, {0.,1.,0.}}; /*---------------------------------------------------------------------- Generate a Surface Mesh, Curve Mesh and Tet Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_CurvMesh *curvmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf, *connectcurv, *connecttet; Vint i; Vint numsurfpnts, numsurftris; Vint numcurvpnts, numcurvlins; Vint numnp, numel; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,8,12); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* define points */ for (i = 0; i < 8; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); } /* define triangle connectivity */ for (i = 0; i < 12; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.1); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* generate interior curve mesh */ /* create CurvMesh object */ curvmesh = vis_CurvMeshBegin (); vis_CurvMeshDef (curvmesh,2,1); /* create Connect object */ connectcurv = vis_ConnectBegin (); vis_ConnectPre (connectcurv,SYS_DOUBLE); vis_ConnectDef (connectcurv,0,0); /* define points */ for (i = 0; i < 2; i++) { vis_CurvMeshSetPoint (curvmesh,i+1,xe[i],1); } /* define line connectivity */ vis_CurvMeshSetLine (curvmesh,1,lin); vis_CurvMeshSetLineTang (curvmesh,1,tangs); /* set mesh parameters */ vis_CurvMeshSetParami (curvmesh,VIS_MESH_MAXI,3); vis_CurvMeshSetParamd (curvmesh,VIS_MESH_EDGELENGTH,.005); /* generate */ vis_CurvMeshGenerate (curvmesh,connectcurv); if(vis_CurvMeshError (curvmesh)) { printf("curv mesh generation error\n"); exit(1); } else { printf("curv mesh generation complete\n"); } /* print number of curve nodes and elements */ vis_ConnectNumber (connectcurv,SYS_NODE,&numcurvpnts); vis_ConnectNumber (connectcurv,SYS_ELEM,&numcurvlins); printf(" Number of nodes= %d\n",numcurvpnts); printf(" Number of lines= %d\n",numcurvlins); /* add curve mesh to surface mesh */ vis_ConnectAppend (connectsurf,connectcurv); vis_ConnectMerge (connectsurf,NULL); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,2); /* fill with boundary elements */ vis_TetMeshConnect (tetmesh,connectsurf); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,.1); /* create Connect object to hold generated tet mesh */ connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connecttet); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam48g.bdf"); /* end objects */ vis_ConnectEnd (connectsurf); vis_ConnectEnd (connectcurv); vis_ConnectEnd (connecttet); vis_SurfMeshEnd (surfmesh); vis_CurvMeshEnd (curvmesh); vis_TetMeshEnd (tetmesh); return 0; }
The surface geometry of the cantilever beam is entered into the SurfMesh module as a set of points, connecting triangles and preserved edges. Two sets of triangle "face" associations are defined at the ends of the beam to identify generated nodes to apply restraints and loading conditions. The nodes for restraints are identified by node association VIS_MISCID1 and nodes for loading are identified by node association VIS_MISCID2. The surface mesh is generated and input to the TetMesh module for tetrahedralization. The surface mesh is not altered by the tet meshing process. All surface triangles will be preserved as faces of tetrahedra and all surface nodes and their numbering are unaltered. Once the tetrahedral mesh is complete, a Model object hierarchy is generated to hold the generated mesh and all required material properties, restraints, loading and solution properties. The Model object is a container for other objects which provide a complete description of a finite element model. The Connect object containing the node coordinates and element connectivity is registered in the Model object. In this example material properties, element properties, restraints cases and load cases are registered in Model as HashTable objects of MProp, EProp, RCase and LCase objects respectively. Two solution property objects, SProp, are created to control the solution for each of the two load cases and are entered into a List object which is subsequently registered in the Model object.
One the Model object is fully populated with it's component objects the vis_ModelWrite function is used to write the model to a file in NASTRAN Bulk Data Format. Then the VdmTools modules NatLib, DataFun and LMan, are used to export the model to a native .vdm file. Finally the model hierarchy is deleted.
#include <math.h> #include <stdio.h> #include <stdlib.h> #include "base/base.h" #include "vis/vismesh.h" #include "vdm/vdm.h" /* useful macro for parsing group activity flags */ #define VIEW_FLAG(flags,ind) (((flags) >> ((ind)-1)) & 1) /* points defining corners of cantilever beam */ static Vdouble pnts[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,10.}, {1.,0.,10.}, {0.,1.,10.}, {1.,1.,10.} }; /* triangles defining surface of cantilever beam */ static Vint tris[12][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8} }; /* triangles edges to be preserved */ static Vint efls[12][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,0}, {0,0,1}, {0,1,0}, {0,0,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }; /*---------------------------------------------------------------------- Generate 3D Volume Tet Model and Write to .vdm File ----------------------------------------------------------------------*/ int main(int argc, char **argv) { Vint i, k; vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_Connect *connectsurf; vis_Group *groupface, *groupnode; vis_Model *model; vis_Connect *connect; vis_GridFun *gridfun; vis_MProp *mprop; vis_EProp *eprop; vis_SProp *sprop; vis_RCase *rcase; vis_LCase *lcase; vsy_HashTable *mphash, *ephash, *rchash, *lchash; vsy_List *splist; vdm_DataFun *datafun; vdm_NatLib *natlib; vdm_LMan *lman; Vint numpnts, numtris; Vdouble x[3]; Vint nix, tri[6]; Vint numsurfpnts, numsurftris; Vint numtetpnts, numtets; Vint flag, maxi; Vdouble edgelen; Vchar outpath[256]; Vint no; Vint aid; Vdouble v[10][3], temp; /* check for proper number of arguments */ if(argc < 2) { fprintf(stderr,"Usage: %s outputfile\n",argv[0]); fprintf(stderr," outputfile is blank, exam49vdm.vdm is assumed\n"); strcpy(outpath,"exam49vdm.vdm"); } else { strcpy(outpath,argv[1]); } /* element order */ maxi = 3; numpnts = 8; numtris = 12; /* instance surf mesher */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* define input points */ for(i = 1; i <= numpnts; i++) { vis_SurfMeshSetPoint (surfmesh,i,pnts[i-1],0); } /* define input triangles and preserved edge flags */ for(i = 1; i <= numtris; i++) { vis_SurfMeshSetTri (surfmesh,i,tris[i-1],efls[i-1]); } /* define node associations at z=0. for restraints */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID1, 9,SYS_FACE,0,1); vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID1,10,SYS_FACE,0,1); /* define node associations at z=10. for loads */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID2,11,SYS_FACE,0,1); vis_SurfMeshSetTriAssoc (surfmesh,VIS_MISCID2,12,SYS_FACE,0,1); /* instance Connect object to hold generated surface tris */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* set target edge length */ edgelen = .50; vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelen); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.2*edgelen); /* set span angles, etc. */ vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,30.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINANGLE,20.); vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,maxi); /* generate quality surface mesh */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surface mesh generation error\n"); exit(1); } else { printf("surface mesh generation complete\n"); } /* find out the number of generated nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfpnts); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurftris); printf(" Number of nodes= %d\n",numsurfpnts); printf(" Number of tris = %d\n",numsurftris); /* create TetMesh object */ tetmesh = vis_TetMeshBegin (); vis_TetMeshDef (tetmesh,numsurfpnts,numsurftris,maxi); /* fill TetMesh object with generated points on surface */ for(i = 1; i <= numsurfpnts; i++) { vis_ConnectCoordsdv (connectsurf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* fill TetMesh object with generated triangles */ for(i = 1; i <= numsurftris; i++) { vis_ConnectElemNode (connectsurf,i,&nix,tri); vis_TetMeshSetTri (tetmesh,i,tri); } /* create Connect object to hold generated tet mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,edgelen); /* generate mesh */ vis_TetMeshGenerate (tetmesh,connect); if(vis_TetMeshError (tetmesh)) { printf("tet mesh generation error\n"); exit(1); } else { printf("tet mesh generation complete\n"); } /* find out the number of generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numtetpnts); vis_ConnectNumber (connect,SYS_ELEM,&numtets); printf(" Number of nodes= %d\n",numtetpnts); printf(" Number of tets = %d\n",numtets); vis_ConnectKernel (connect,0); /* set property identifier 1 for each element */ for(i = 1; i <= numtets; i++) { vis_ConnectSetElemAssoc (connect,VIS_PROPID,i,1); } /* instance a GridFun object */ gridfun = vis_GridFunBegin (); vis_ConnectGridFun (connect,gridfun); /* create Model object hierarchy */ model = vis_ModelBegin (); /* material and element property hash tables */ mphash = vsy_HashTableBegin (); ephash = vsy_HashTableBegin (); /* restraint and load case hash tables */ rchash = vsy_HashTableBegin (); lchash = vsy_HashTableBegin (); /* solution property list */ splist = vsy_ListBegin (); /* isotropic material 1 */ mprop = vis_MPropBegin (); vis_MPropDef (mprop,SYS_MAT_ISOTROPIC); vis_MPropSetValued (mprop,MPROP_E,1.e+7); vis_MPropSetValued (mprop,MPROP_NU,.3); vis_MPropSetValued (mprop,MPROP_DENSITY,0.0000133); vis_MPropSetValued (mprop,MPROP_A,0.000254); vis_MPropSetValued (mprop,MPROP_TREF,70.0); vsy_HashTableInsert (mphash,1,mprop); /* solid property 1 */ eprop = vis_EPropBegin (); vis_EPropDef (eprop,VIS_ELEM_SOLID); vis_EPropSetValuei (eprop,EPROP_MID,1); vsy_HashTableInsert (ephash,1,eprop); /* restraint case 1 */ rcase = vis_RCaseBegin (); for(i = 1; i <= numsurfpnts; i++) { vis_ConnectNodeAssoc (connectsurf,VIS_MISCID1,1,&i,&aid); if(aid) { vis_RCaseSetSPC (rcase,i,SYS_DOF_TX,RCASE_FIXED,NULL,0); vis_RCaseSetSPC (rcase,i,SYS_DOF_TY,RCASE_FIXED,NULL,0); vis_RCaseSetSPC (rcase,i,SYS_DOF_TZ,RCASE_FIXED,NULL,0); } } vsy_HashTableInsert (rchash,1,rcase); /* load node associations to query for element faces */ groupnode = vis_GroupBegin(); vis_GroupDef (groupnode,numtetpnts,SYS_NODE,SYS_NONE); for(i = 1; i <= numsurfpnts; i++) { vis_ConnectNodeAssoc (connectsurf,VIS_MISCID2,1,&i,&aid); vis_GroupSetIndex (groupnode,i,aid); } /* build face group to query for element faces */ groupface = vis_GroupBegin(); vis_GroupDef (groupface,numtets,SYS_ELEM,SYS_FACE); vis_ConnectFaceGroup (connect,CONNECT_CONTAINED,groupnode,groupface); /* load case 1, distributed load */ lcase = vis_LCaseBegin (); vis_LCaseSetObject (lcase,VIS_GRIDFUN,gridfun); for(k = 0; k < 10; k++) { v[k][0] = 0.; v[k][1] = 1.; v[k][2] = 0.; } for(i = 1; i <= numtets; i++) { vis_GroupGetIndex (groupface,i,&flag); if(flag == 0) continue; for(no = 1; no <= 6; no++) { if(VIEW_FLAG(flag,no)) { vis_LCaseSetDistdv (lcase,SYS_FACE,i,no,LCASE_TRAC,(Vdouble*)v); } } } vsy_HashTableInsert (lchash,1,lcase); /* load case 2, thermal load, soak temperature of 1000. */ lcase = vis_LCaseBegin (); temp = 1000.; for(i = 1; i <= numtetpnts; i++) { vis_LCaseSetConcdv (lcase,i,LCASE_TEMP,&temp); } vsy_HashTableInsert (lchash,2,lcase); /* solution step 1 */ sprop = vis_SPropBegin (); vis_SPropDef (sprop,SYS_SOL_STATIC); vis_SPropSetValuec (sprop,SPROP_TITLE,"Example 49"); vis_SPropSetValuei (sprop,SPROP_ANALYSIS,SYS_ANALYSIS_STRUCTURAL); vis_SPropSetValuei (sprop,SPROP_RCASE,1); vis_SPropSetValued (sprop,SPROP_RCASE_FACTOR,1.); vis_SPropSetValuei (sprop,SPROP_LCASE_NUM,1); vis_SPropSetValuei (sprop,SPROP_LCASE,1); vis_SPropSetValued (sprop,SPROP_LCASE_FACTOR,1.); vsy_ListInsert (splist,1,sprop); /* solution step 2 */ sprop = vis_SPropBegin (); vis_SPropDef (sprop,SYS_SOL_STATIC); vis_SPropSetValuei (sprop,SPROP_ANALYSIS,SYS_ANALYSIS_STRUCTURAL); vis_SPropSetValuei (sprop,SPROP_RCASE,1); vis_SPropSetValued (sprop,SPROP_RCASE_FACTOR,1.); vis_SPropSetValuei (sprop,SPROP_LCASE_NUM,1); vis_SPropSetValuei (sprop,SPROP_LCASE,2); vis_SPropSetValued (sprop,SPROP_LCASE_FACTOR,1.); vis_SPropSetValuei (sprop,SPROP_THERMALSTRAIN,SYS_ON); vsy_ListInsert (splist,2,sprop); /* register Connect in Model */ vis_ModelSetObject (model,VIS_CONNECT,connect); /* register property hashtables and lists in Model */ vis_ModelSetHashTable (model,VIS_MPROP,mphash); vis_ModelSetHashTable (model,VIS_EPROP,ephash); vis_ModelSetList (model,VIS_SPROP,splist); /* register case hashtables in Model */ vis_ModelSetHashTable (model,VIS_RCASE,rchash); vis_ModelSetHashTable (model,VIS_LCASE,lchash); printf("model definition complete\n"); /* write NASTRAN Bulk Data File */ vis_ModelWrite (model,SYS_NASTRAN_BULKDATA,"exam49vdm.bdf"); printf("model written to NASTRAN Bulk Data file %s\n","exam49vdm.bdf"); vis_ModelWrite (model,SYS_ABAQUS_INPUT,"exam49vdm.inp"); printf("model written to ABAQUS Input Data file %s\n","exam49vdm.inp"); /* save model to .vdm */ natlib = vdm_NatLibBegin(); datafun = vdm_DataFunBegin (); lman = vdm_LManBegin (); vdm_NatLibDataFun (natlib,datafun); vdm_DataFunSetConvention (datafun,VDM_CONVENTION_DOUBLE); vdm_DataFunSetStatus (datafun,VDM_STATUS_NEW); vdm_DataFunOpen (datafun,0,outpath,VDM_NATIVE); vdm_LManSetObject (lman,VDM_DATAFUN,datafun); vdm_LManSaveModel (lman,model); vdm_DataFunClose (datafun); vdm_LManEnd (lman); vdm_DataFunEnd (datafun); vdm_NatLibEnd (natlib); printf("model saved on native .vdm output file %s\n",outpath); /* delete objects */ vis_SurfMeshEnd (surfmesh); vis_ConnectEnd (connectsurf); vis_TetMeshEnd (tetmesh); vis_GridFunEnd (gridfun); vis_GroupEnd (groupface); vis_GroupEnd (groupnode); /* delete model heirarchy */ vis_ConnectEnd (connect); vsy_HashTableForEach (ephash,(void(*)(Vobject*))vis_EPropEnd); vsy_HashTableEnd (ephash); vsy_HashTableForEach (mphash,(void(*)(Vobject*))vis_MPropEnd); vsy_HashTableEnd (mphash); vsy_ListForEach (splist,(void(*)(Vobject*))vis_SPropEnd); vsy_ListEnd (splist); vsy_HashTableForEach (rchash,(void(*)(Vobject*))vis_RCaseEnd); vsy_HashTableEnd (rchash); vsy_HashTableForEach (lchash,(void(*)(Vobject*))vis_LCaseEnd); vsy_HashTableEnd (lchash); vis_ModelEnd (model); return 0; }
The original input triangulation is a prism defined by 8 triangles. This prism may not be meshed with no interior points without refining the surface triangulation. The example iterates until the TetMesh module succeeds in generating a tetrahedral mesh with no addition points generated.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[6][3] = { {0.,0.,0.}, {2.,0.,0.}, {1.,1.,0.}, {0.,0.,1.}, {2.,0.,1.}, {1.,1.,1.} }; static Vint tris[8][3] = { {1,3,2}, {4,5,6}, {1,2,4}, {2,5,4}, {2,3,5}, {5,3,6}, {6,3,1}, {6,1,4} }; void loadsurface(vis_Connect *connectsrf); void readsurface(vis_Connect *connectsrf, Vchar *path); int generatetetmesh(vis_Connect *connectsrf, vis_Connect *connecttet); void refinesurface(vis_Connect *connectsrf, vis_Connect *connecttet); /*---------------------------------------------------------------------- Generate a 3D Volume Tet Mesh with No Interior Points ----------------------------------------------------------------------*/ int main(int argc, char **argv) { vis_Connect *connectsrf; vis_Connect *connecttet; Vint numnod, numtri; Vint numnp, numel; Vint istat, imesh, ifail; /* create connect object of surface */ connectsrf = vis_ConnectBegin (); vis_ConnectPre (connectsrf,SYS_DOUBLE); vis_ConnectDef (connectsrf,0,0); /* load surface from static arrays */ if(argc < 2) { loadsurface (connectsrf); /* read surface from TetMeshWrite file */ } else { readsurface (connectsrf,argv[1]); } /* convert to dynamic mode */ vis_ConnectMode (connectsrf,CONNECT_DYNAMIC); /* create tet mesh given surface triangles */ /* enter refinement loop, try 3 times */ for(imesh = 0; imesh < 100; imesh++) { printf("iteration= %d\n",imesh); vis_ConnectNumber (connectsrf,SYS_NODE,&numnod); vis_ConnectNumber (connectsrf,SYS_ELEM,&numtri); printf("numnod= %d, numtri= %d\n",numnod,numtri); connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_ConnectDef (connecttet,0,0); /* generate tet mesh */ istat = generatetetmesh (connectsrf,connecttet); if(istat) { ifail = 0; printf("TetMesh generation failure\n"); break; } vis_ConnectNumber (connecttet,SYS_NODE,&numnp); vis_ConnectNumber (connecttet,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* check for no interior points */ if(numnp == numnod) { ifail = 0; printf("no interior points generated\n"); vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,"exam50.bdf"); break; } printf("number of interior points= %d \n",numnp-numnod); ifail = 1; /* refine surface mesh */ refinesurface (connectsrf,connecttet); vis_ConnectEnd (connecttet); } /* end objects */ vis_ConnectEnd (connectsrf); if(ifail == 0) { vis_ConnectEnd (connecttet); } return 0; } void loadsurface(vis_Connect *connectsrf) { Vint i; printf("load surface from static arrays\n"); /* set nodes */ for(i = 0; i < 6; i++) { vis_ConnectSetCoordsdv (connectsrf,i+1,coords[i]); } /* set triangles */ for(i = 0; i < 8; i++) { vis_ConnectSetTopology (connectsrf,i+1,VIS_SHAPETRI,2,0,0); vis_ConnectSetElemNode (connectsrf,i+1,tris[i]); } } void readsurface(vis_Connect *connectsrf, Vchar *path) { vis_TetMesh *tetmesh; vis_Connect *connect; printf("read surface from file: %s\n",path); /* create tetmesh object to import TetMeshWrite file */ tetmesh = vis_TetMeshBegin(); /* read file */ if(strstr(path,".tet") != NULL) { vis_TetMeshRead (tetmesh,SYS_ASCII,path); } else if(strstr(path,".btet") != NULL) { vis_TetMeshRead (tetmesh,SYS_BINARY,path); } /* get internal connect object */ vis_TetMeshGetConnect (tetmesh,&connect); /* copy it */ vis_ConnectCopy (connectsrf,connect); /* destroy tetmesh object */ vis_TetMeshEnd (tetmesh); } int generatetetmesh(vis_Connect *connectsrf, vis_Connect *connecttet) { Vint i; vis_TetMesh *tetmesh; Vint numnod, numtri; Vdouble x[3]; Vint nix, ix[3]; Vint ierr; /* create tetmesh object */ tetmesh = vis_TetMeshBegin (); vis_ConnectNumber (connectsrf,SYS_NODE,&numnod); vis_ConnectNumber (connectsrf,SYS_ELEM,&numtri); vis_TetMeshDef (tetmesh,numnod,numtri,2); /* define nodes */ for(i = 1; i <= numnod; i++) { vis_ConnectCoordsdv (connectsrf,1,&i,(Vdouble(*)[3])x); vis_TetMeshSetNode (tetmesh,i,x); } /* define tris */ for(i = 1; i <= numtri; i++) { vis_ConnectElemNode (connectsrf,i,&nix,ix); vis_TetMeshSetTri (tetmesh,i,ix); } /* try for no interior points */ vis_TetMeshSetParami (tetmesh,VIS_MESH_INTERREFINE,VIS_OFF); /* generate */ vis_TetMeshGenerate (tetmesh,connecttet); ierr = vis_TetMeshError (tetmesh); vis_TetMeshEnd (tetmesh); return ierr; } void refinesurface(vis_Connect *connectsrf, vis_Connect *connecttet) { Vint i, j, k; Vint numtrinod; Vint numtetnod; Vint nix, ix[4]; Vint nixa, ixa[1000]; Vint nint, kint, next, kext[3]; Vint nixext, ixext; Vint nixed, ixed[3]; Vdouble xa[2][3], xc[3]; Vint ntrinod; Vdouble s, smax; Vint kmax; vis_ConnectNumber (connectsrf,SYS_NODE,&numtrinod); vis_ConnectNumber (connecttet,SYS_NODE,&numtetnod); vis_ConnectKernel (connecttet,0); ntrinod = numtrinod; /* loop through interior nodes, get connected tets */ for(i = numtrinod+1; i <= numtetnod; i++) { vis_ConnectNodeElem (connecttet,i,&nixa,ixa); /* loop through adjacent tets, get exterior nodes */ for(j = 0; j < nixa; j++) { vis_ConnectElemNode (connecttet,ixa[j],&nix,ix); nint = 0; next = 0; for(k = 0; k < nix; k++) { if(ix[k] <= numtrinod) { kext[next] = ix[k]; next += 1; } else { kint = k; nint += 1; } } /* if more than one interior point, skip */ if(nint != 1) continue; vis_ConnectNodeAdj (connectsrf,3,kext,&nixext,&ixext); /* if not exactly one surface triangle, skip */ if(nixext != 1) continue; /* split longest edge */ smax = 0.; for(k = 1; k <= 3; k++) { vis_ConnectSizeElemdv (connectsrf,SYS_EDGE,ixext,k,&s); if(s >= smax) { smax = s; kmax = k; } } /* generate point at center of edge */ vis_ConnectElemCon (connectsrf,SYS_EDGE,ixext,kmax,&nixed,ixed); vis_ConnectCoordsdv (connectsrf,nixed,ixed,xa); xc[0] = (xa[0][0] + xa[1][0])/2.; xc[1] = (xa[0][1] + xa[1][1])/2.; xc[2] = (xa[0][2] + xa[1][2])/2.; ntrinod += 1; vis_ConnectSetCoordsdv (connectsrf,ntrinod,xc); vis_ConnectSplitElem (connectsrf,SYS_EDGE,ixext,kmax,ntrinod); printf("split elem= %d, edge= %d, node= %d\n",ixext,kmax,ntrinod); break; } } }
The example starts with a set of overlapping two-dimensional regions defined by straight segments. Each segment is assigned a region with a VIS_PROPID element association. vis_ConnectTess is then invoked to generate a Connect object with non-intersecting segments. This is used, in turn, as the boundary for a two-dimensional tesselation of the interior of the boundary using TriMesh. No interior points are generated by TriMesh.
The initial triangulation generated with TriMesh is then used as input for a quality triangulation using SurfMesh. The final triangulation is written as a NATRAN bulk data file. However, in order to illustrate the multiple element associations inherited by overlapping regions, these associations are sent to the output console.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble x[20][3] = { {1.,0.,0.}, {4.,0.,0.}, {0.,3.,0.}, {1.,3.,0.}, {4.,3.,0.}, {5.,3.,0.}, {2.,4.,0.}, {4.,4.,0.}, {1.,5.,0.}, {3.,5.,0.}, {2.,6.,0.}, {4.,6.,0.}, {1.,7.,0.}, {3.,7.,0.}, {0.,8.,0.}, {5.,8.,0.}, {2.,1.,0.}, {3.,1.,0.}, {2.,2.,0.}, {3.,2.,0.} }; static Vint ix[20][2] = { { 1, 2}, { 2, 5}, { 5, 4}, { 4, 1}, { 3, 6}, { 6,16}, {16,15}, {15, 3}, { 9,10}, {10,14}, {14,13}, {13, 9}, { 7, 8}, { 8,12}, {12,11}, {11, 7}, {17,19}, {19,20}, {20,18}, {18,17} }; /*---------------------------------------------------------------------- Tesselate and Mesh a Bounded Region in a Plane ----------------------------------------------------------------------*/ int main() { vis_Connect *connect, *tess; vis_TriMesh *trimesh; vis_SurfMesh *surfmesh; Vint n, numnp, numel, nix, jx[3], aid[20], num, k, efls[3], i; Vdouble xd[3]; /* define original geometry */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); for(n = 1; n <= 20; n++) { vis_ConnectSetCoordsdv (connect,n,x[n-1]); } for(n = 1; n <= 20; n++) { vis_ConnectSetTopology (connect,n,SYS_SHAPELINE,2,0,0); vis_ConnectSetElemNode (connect,n,ix[n-1]); vis_ConnectSetElemAssoc (connect,VIS_PROPID,n,(n-1)/4+1); } vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam51-bound.bdf"); /* tesselate geometry */ tess = vis_ConnectBegin (); vis_ConnectPre (tess,SYS_DOUBLE); vis_ConnectTess (tess,connect); vis_ConnectEnd (connect); vis_ConnectWrite (tess,SYS_NASTRAN_BULKDATA,"exam51-tess.bdf"); vis_ConnectNumber (tess,SYS_NODE,&numnp); vis_ConnectNumber (tess,SYS_ELEM,&numel); /* create trimesh object */ trimesh = vis_TriMeshBegin (); vis_TriMeshDef (trimesh,numnp,numel,2); vis_TriMeshSetParamd (trimesh,VIS_MESH_EDGELENGTH,10.); /* define trimesh nodes */ for(n = 1; n <= numnp; n++) { vis_ConnectCoordsdv (tess,1,&n,(Vdouble(*)[3])xd); vis_TriMeshSetNode (trimesh,n,xd); } /* define trimesh lines */ for(n = 1; n <= numel; n++) { vis_ConnectElemNode (tess,n,&nix,jx); vis_TriMeshSetLine (trimesh,n,jx); vis_ConnectAllElemAssoc (tess,VIS_PROPID,n,&num,aid); for(k = 0; k < num; k++) { vis_TriMeshSetLineAssoc (trimesh,VIS_PROPID,n,SYS_ELEM,aid[k]); vis_TriMeshSetLineAssoc (trimesh,VIS_PROPID,n,SYS_EDGE,aid[k]); } } vis_ConnectEnd (tess); connect = vis_ConnectBegin (); vis_TriMeshWrite (trimesh,SYS_ASCII,"exam51.tri"); vis_TriMeshGenerate (trimesh,connect); vis_TriMeshEnd (trimesh); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam51-tri.bdf"); /* use output from TriMesh as input to SurfMesh */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numnp,numel); for(n = 1; n <= numnp; n++) { vis_ConnectCoordsdv (connect,1,&n,(Vdouble(*)[3])xd); vis_SurfMeshSetPoint (surfmesh,n,xd,1); } for(n = 1; n <= numel; n++) { vis_ConnectElemNode (connect,n,&nix,jx); efls[0] = efls[1] = efls[2] = 0; for(i = 1; i <= 3; i++) { vis_ConnectAllElemEntAssoc (connect,VIS_PROPID,SYS_EDGE,n,i,&num,aid); if(num) { if(aid[0]) { efls[i-1] = 1; } } } vis_SurfMeshSetTri (surfmesh,n,jx,efls); for(i = 1; i <= 3; i++) { vis_ConnectAllElemEntAssoc (connect,VIS_PROPID,SYS_EDGE,n,i,&num,aid); if(num) { for(k = 0; k < num; k++) { vis_SurfMeshSetTriAssoc(surfmesh,VIS_PROPID,n,SYS_EDGE,i,aid[k]); } } } vis_ConnectAllElemAssoc (connect,VIS_PROPID,n,&num,aid); if(num) { for(k = 0; k < num; k++) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,n,SYS_ELEM,1,aid[k]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,n,SYS_FACE,1,aid[k]); } } } vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,0.5); vis_ConnectEnd (connect); connect = vis_ConnectBegin (); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam51.srf"); vis_SurfMeshGenerate (surfmesh,connect); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam51-srf.bdf"); /* print result */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Nodes:\n"); for(n = 1; n <= numnp; n++) { vis_ConnectCoordsdv (connect,1,&n,(Vdouble(*)[3])xd); printf("node= %d, x= %e, y= %e\n",n,xd[0],xd[1]); } printf("Elements:\n"); for(n = 1; n <= numel; n++) { vis_ConnectElemNode (connect,n,&nix,jx); printf("elem= %d, nodes= %d %d %d, assoc= ",n,jx[0],jx[1],jx[2]); vis_ConnectAllElemAssoc (connect,VIS_PROPID,n,&num,aid); for(k = 0; k < num; k++) { printf("%d ",aid[k]); } printf("\n"); } /* end objects */ vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
#include "base/base.h" #include "vis/vismesh.h" #include <float.h> #include "spatial_license.h" #include "license.hxx" #include "acis.hxx" #include "api.hxx" #include "ga_api.hxx" #include "at_name.hxx" #include "at_int.hxx" #include "kernapi.hxx" #include "ckoutcom.hxx" #include "transf.hxx" #include "transfrm.hxx" #include "geometry.hxx" #include "curve.hxx" #include "curdef.hxx" #include "body.hxx" #include "vertex.hxx" #include "point.hxx" #include "coedge.hxx" #include "edge.hxx" #include "loop.hxx" /* GHF #define VKI_PROJECT_WIRES */ #define VKI_PROJECT_CONICS #ifdef VKI_PROJECT_CONICS #include "cone.hxx" #include "sphere.hxx" #include "torus.hxx" #include "plane.hxx" #include "getowner.hxx" #endif #include "cstrapi.hxx" #include "af_api.hxx" #include "LinkedMeshManager.hxx" #include "idx_mesh.hxx" #include "stlmmg.hxx" #include "gmeshmg.hxx" #include "cface.hxx" #include "at_fcf.hxx" #include "cell2d.hxx" #include "cshell.hxx" #include "intrapi.hxx" #include "ptlist.hxx" #include "license.hxx" #include "spa_unlock_result.hxx" #ifdef OLDLICENSE extern void unlock_spatial_products_6831(); #endif /* SurfMesh geometry projection callback function */ void project_surfmesh2acis(vis_SurfMesh *surfmesh, Vobject *object, Vint enttype, Vint entaid, Vdouble uh[], Vdouble xh[3], Vdouble ug[], Vdouble xg[3]) { SPAposition pxh(xh[0],xh[1],xh[2]); SPAposition pxg; double distance; param_info ent_info; ENTITY *ent; outcome res; res = api_get_entity_from_id(--entaid,ent); check_outcome(res); res = api_entity_point_distance(ent,pxh,pxg,distance,ent_info); check_outcome(res); if(enttype == SYS_EDGE) { ug[0] = ent_info.t(); } else if(enttype == SYS_FACE) { ug[0] = ent_info.uv().u; ug[1] = ent_info.uv().v; } xg[0] = pxg.x(); xg[1] = pxg.y(); xg[2] = pxg.z(); } /* ACIS initialization function */ static void init_acis() { #ifdef OLDLICENSE unlock_spatial_products_6831(); #endif check_outcome(api_start_modeller(0)); check_outcome(api_initialize_faceter()); } /* ACIS termination function */ static void term_acis() { api_terminate_faceter(); api_stop_modeller(); } static void associate_to_cshell(CFACE *cface, tag_id_type *id) { if(cface == NULL) return; if(cface->owner()->identity() == CELL2D_TYPE) return; CSHELL *cshell = (CSHELL*)cface->owner(); CELL* cell = (CELL*)cshell->owner(); api_get_entity_id (reinterpret_cast(cell),*id); *id += 1; } static logical calculate_edge_tangents(EDGE* edge, SPAposition pos, Vdouble tpar, Vdouble tv[3]) { SPAunit_vector tang; SPAvector tan_vec; if(tpar == DBL_MAX) { if(same_point (pos, edge->start_pos(), SPAresabs)) { tpar = edge->start_param(); } else if(same_point (pos, edge->end_pos(), SPAresabs)) { tpar = edge->end_param(); } if(tpar == DBL_MAX) { tv[0] = 0.; tv[1] = 0.; tv[2] = 0.; return(0); } } tan_vec = edge->geometry()->equation().eval_deriv(tpar,TRUE,TRUE); tang = normalise (tan_vec); tv[0] = tang.x(); tv[1] = tang.y(); tv[2] = tang.z(); return(1); } /* ACIS mesh manager */ class VKI_MESH_MANAGER : public GLOBAL_MESH_MANAGER { private: vis_SurfMesh *surfmesh; Vint tix[3]; /* triangle connectivity */ Vdouble norms[3][3]; /* triangle node normals */ Vdouble tangs[3][3]; /* triangle node tangents */ Vint efl[3]; /* triangle edge flags */ Vint reversed[3]; /* coedge direction */ tag_id_type edge_id[3]; /* edge entity tags for triangle */ tag_id_type face_id; /* face entity tag for triangle */ Vint conicid; /* conic id */ Vint hasconic; /* current face has conic */ Vint nodeind; /* current defined point */ Vint elemind; /* current defined triangle */ Vint ibody; /* current body */ Vint rfaceflag; Vint lfaceflag; tag_id_type rfaceid; /* back cell */ tag_id_type lfaceid; /* front cell */ public: VKI_MESH_MANAGER(vis_SurfMesh *surfMesh) { surfmesh = surfMesh; nodeind = 0; elemind = 0; face_id = 0; conicid = 0; hasconic = 0; rfaceflag = 0; lfaceflag = 0; rfaceid = 0; lfaceid = 0; ibody = 0; } virtual logical need_global_indexed_polygons (void) { return TRUE; } virtual logical need_precount_of_global_indexed_polygons(void) { return TRUE; } virtual logical need_coedge_pointers_on_polyedges() { return TRUE; } virtual logical need_indexed_polynode_with_data() { return TRUE; } virtual logical need_edge_indices() { return TRUE; } virtual void* null_node_id(void) { return (void *) -1; } virtual void* announce_global_node(int inode, VERTEX *ver, const SPAposition &Xi) { Vdouble x[3]; tag_id_type id; /* set point coordinates */ x[0]=Xi.x(); x[1]=Xi.y(); x[2]=Xi.z(); nodeind = inode + 1; vis_SurfMeshSetPoint (surfmesh,nodeind,x,1); /* recover and set vertex geometry tag */ api_get_entity_id((ENTITY*)ver,id); /* offset by one to ensure a non-zero tag */ id += 1; vis_SurfMeshSetPointAssoc (surfmesh,VIS_GEOVERT,nodeind,id); return((void*)inode); } virtual void* announce_global_node(int inode, EDGE* mod_edge, const SPAposition &Xi, double t) { Vdouble x[3]; /* set point coordinates */ x[0]=Xi.x(); x[1]=Xi.y(); x[2]=Xi.z(); nodeind = inode + 1; vis_SurfMeshSetPoint (surfmesh,nodeind,x,0); return((void*)inode); } virtual void* announce_global_node(int inode, FACE* mod_face, const SPAposition &Xi, const SPApar_pos &uv) { Vdouble x[3]; /* set point coordinates */ x[0]=Xi.x(); x[1]=Xi.y(); x[2]=Xi.z(); nodeind = inode + 1; vis_SurfMeshSetPoint (surfmesh,nodeind,x,0); return((void*)inode); } virtual void announce_polygon_model_face(ENTITY* ent) { FACE *face = (FACE*)ent; Vint sense; Vdouble xo[3], ax[3], dt[3], radius, mag, angle; /* set geometry face tag for oncoming polygons */ api_get_entity_id((ENTITY*)ent,face_id); /* offset by one to ensure a non-zero tag */ face_id += 1; hasconic = 0; logical face_sense = (face->sense() == REVERSED); if(face_sense) { sense = -1; } else { sense = 1; } /* conic sections */ #ifdef VKI_PROJECT_CONICS { /* GHF */ printf("face_id= %d\n",face_id); printf("sense= %d\n",sense); SPAtransf T = SPAtransf(); T = get_owner_transf(face); if(is_conical_face(face)) { cone const &the_cone = (cone const &)(face->geometry()->equation()); SPAposition the_cone_apex = the_cone.get_apex(); ellipse ell = the_cone.base; SPAposition center = ell.centre; SPAunit_vector nor = ell.normal; SPAvector axis = ell.major_axis; Vdouble radius_ratio = ell.radius_ratio; Vdouble sine_angle = the_cone.sine_angle; /* GHF */ printf("conical face\n"); printf("center= %e %e %e\n",center.x(),center.y(),center.z()); printf("nor= %e %e %e\n",nor.x(),nor.y(),nor.z()); printf("axis= %e %e %e\n",axis.x(),axis.y(),axis.z()); printf("radius_ratio= %e\n",radius_ratio); printf("sine_angle= %e\n",sine_angle); if(radius_ratio == 1.) { conicid += 1; hasconic = 1; xo[0] = center.x(); xo[1] = center.y(); xo[2] = center.z(); ax[0] = nor.x(); ax[1] = nor.y(); ax[2] = nor.z(); dt[0] = axis.x(); dt[1] = axis.y(); dt[2] = axis.z(); radius = sqrt(dt[0]*dt[0] + dt[1]*dt[1] + dt[2]*dt[2]); dt[0] = dt[0]/radius; dt[1] = dt[1]/radius; dt[2] = dt[2]/radius; if(sine_angle == 0.) { vis_SurfMeshSetConic (surfmesh,conicid,SURFMESH_CONIC_CYLINDER, sense,xo,ax,dt,radius,0.); } else { angle = fabs(sine_angle); vis_SurfMeshSetConic (surfmesh,conicid,SURFMESH_CONIC_CONE, sense,xo,ax,dt,angle,0.); } } } else if(is_toroidal_face(face)) { torus const& tor = (torus const&)(face->geometry()->equation()); SPAposition center = tor.centre; SPAunit_vector normal = tor.normal; SPAunit_vector ref = tor.uv_oridir; double major_radius = tor.major_radius; double minor_radius = tor.minor_radius; /* GHF */ printf("toroidal face\n"); conicid += 1; hasconic = 1; xo[0] = center.x(); xo[1] = center.y(); xo[2] = center.z(); ax[0] = normal.x(); ax[1] = normal.y(); ax[2] = normal.z(); dt[0] = ref.x(); dt[1] = ref.y(); dt[2] = ref.z(); major_radius = fabs(major_radius); minor_radius = fabs(minor_radius); vis_SurfMeshSetConic (surfmesh,conicid,SURFMESH_CONIC_TORUS, sense,xo,ax,dt,minor_radius,major_radius); } else if(is_spherical_face(face)) { sphere *sph = (sphere*)(face->geometry()->trans_surface(T,face_sense)); SPAposition center = sph->centre; SPAunit_vector normal = sph->pole_dir; SPAunit_vector ref = sph->uv_oridir; radius = sph->radius; /* GHF */ printf("spherical face\n"); printf("center= %e %e %e\n",center.x(),center.y(),center.z()); printf("normal= %e %e %e\n",normal.x(),normal.y(),normal.z()); printf("radius= %e\n",radius); conicid += 1; hasconic = 1; xo[0] = center.x(); xo[1] = center.y(); xo[2] = center.z(); ax[0] = normal.x(); ax[1] = normal.y(); ax[2] = normal.z(); dt[0] = ref.x(); dt[1] = ref.y(); dt[2] = ref.z(); radius = fabs(radius); vis_SurfMeshSetConic (surfmesh,conicid,SURFMESH_CONIC_SPHERE, sense,xo,ax,dt,radius,0.); } else if(is_planar_face(face)) { const plane& p = (const plane&)(face->geometry()->equation()); SPAposition pos = p.root_point; SPAunit_vector nor = p.normal; SPAvector ref = p.u_deriv; conicid += 1; hasconic = 1; xo[0] = pos.x(); xo[1] = pos.y(); xo[2] = pos.z(); ax[0] = nor.x(); ax[1] = nor.y(); ax[2] = nor.z(); dt[0] = ref.x(); dt[1] = ref.y(); dt[2] = ref.z(); mag = sqrt(dt[0]*dt[0] + dt[1]*dt[1] + dt[2]*dt[2]); dt[0] = dt[0]/mag; dt[1] = dt[1]/mag; dt[2] = dt[2]/mag; vis_SurfMeshSetConic (surfmesh,conicid,SURFMESH_CONIC_PLANE, sense,xo,ax,dt,0.,0.); /* GHF */ printf("planar face\n"); printf("pos= %e %e %e\n",pos.x(),pos.y(),pos.z()); printf("nor= %e %e %e\n",nor.x(),nor.y(),nor.z()); } } #endif /* determine material presense relative to face */ rfaceflag = 1; lfaceflag = 0; if(face->sides() == DOUBLE_SIDED) { lfaceflag = 1; } ATTRIB_FACECFACE *att = (ATTRIB_FACECFACE*)find_attrib (face,ATTRIB_CT_TYPE, ATTRIB_FACECFACE_TYPE); rfaceid = lfaceid = 0; /* check for cellular topology information */ if(att != NULL) { associate_to_cshell (att->back_cface(), &rfaceid); associate_to_cshell (att->front_cface(),&lfaceid); } } virtual void announce_indexed_polynode(ENTITY* ent, int ipoly, int i, void* idptr, const double &edge_tpar, const SPApar_pos &uv, const SPAposition &pos, const SPAunit_vector &uvec) { EDGE *edge; /* entity is a COEDGE pointer */ /* triangle edge flagged if lie on geometry edge */ efl[i] = (ent!=NULL) ? 1 : 0; /* set triangle normals */ norms[i][0] = uvec.x(); norms[i][1] = uvec.y(); norms[i][2] = uvec.z(); /* set ith triangle point connection */ tix[i] = (long)idptr+1; if(i == 0) { edge_id[0] = edge_id[1] = edge_id[2] = 0; reversed[0] = reversed[1] = reversed[2] = 0; } if(ent == NULL) { return; } /* store the coedge sense */ reversed[i] = ((COEDGE*)ent)->sense() != FORWARD; /* set edge entity tag and tangent */ edge = ((COEDGE*)(ent))->edge(); if (edge && edge->geometry()) { api_get_entity_id((ENTITY*)edge,edge_id[i]); /* offset by one to ensure a non-zero tag */ edge_id[i] += 1; calculate_edge_tangents (edge,pos,edge_tpar,tangs[i]); } } virtual void announce_counts(int numel, int numnp, int npolynode) { if(numnp == 0 || numel == 0) return; vis_SurfMeshDef (surfmesh,numnp,numel); ibody += 1; conicid = 0; } virtual void begin_mesh_output(ENTITY *faceted_entity, ENTITY *refine_entity, ENTITY *output_entity) { } virtual void* announce_indexed_node(int inode, const SPApar_pos ¶m, const SPAposition &Xi, const SPAunit_vector &normal) { Vdouble x[3]; x[0]=Xi.x(); x[1]=Xi.y(); x[2]=Xi.z(); nodeind = inode + 1; vis_SurfMeshSetPoint (surfmesh,nodeind,x,0); return((void*)inode); } virtual void end_mesh_output(ENTITY *faceted_entity, ENTITY *refine_entity, ENTITY *output_entity) { } virtual void start_indexed_polygon(int ipoly, int npolynode, int ishare) { } virtual void announce_indexed_polynode(int ipoly, int i, void *pnode) { } virtual void end_indexed_polygon(int iPoly) { int i, j, i1; Vdouble tv[2][3], t1; Vdouble x0[3], x1[3], dx[3], fl, elen; Vint pflag, oknorm, oktang; EDGE *edge; SPAposition ci, xi; double d; param_info ent_info; elemind = iPoly + 1; vis_SurfMeshSetTri (surfmesh,elemind,tix,efl); /* check for zero normal */ /* we round to 32 bit precision to get rid of noise in the normal values which is inconsistent between successive mesh manager runs on an unchanged model */ oknorm = 1; for(i = 0; i < 3; i++) { norms[i][0] = (float)norms[i][0]; norms[i][1] = (float)norms[i][1]; norms[i][2] = (float)norms[i][2]; fl = norms[i][0]*norms[i][0] + norms[i][1]*norms[i][1] + norms[i][2]*norms[i][2]; if(fl == 0.) { oknorm = 0; break; } } if(oknorm) { vis_SurfMeshSetTriNorm (surfmesh,elemind,norms); } /* tag for nodes generated on geometry edge */ /* compute edge tangents along triangle edge */ for(i = 0; i < 3; i++) { if(edge_id[i]) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,elemind,SYS_EDGE,i+1, edge_id[i]); vis_SurfMeshGetPoint (surfmesh,tix[i],x0,&pflag); tv[0][0] = tangs[i][0]; tv[0][1] = tangs[i][1]; tv[0][2] = tangs[i][2]; i1 = (i+1)%3; vis_SurfMeshGetPoint (surfmesh,tix[i1],x1,&pflag); api_get_entity_from_id (edge_id[i]-1,(ENTITY*&)edge); xi.set_x(x1[0]); xi.set_y(x1[1]); xi.set_z(x1[2]); api_entity_point_distance ((ENTITY*)edge,xi,ci,d,ent_info); if(ent_info.entity_type() == ent_is_vertex) { t1 = reversed[i] ? edge->start_param() : edge->end_param(); if(edge->sense() == REVERSED) { t1 = -t1; } } else { t1 = ent_info.t(); } calculate_edge_tangents (edge,xi,t1,tv[1]); /* align tangents with element connectivity */ dx[0] = x1[0]-x0[0]; dx[1] = x1[1]-x0[1]; dx[2] = x1[2]-x0[2]; elen = sqrt(dx[0]*dx[0]+dx[1]*dx[1]+dx[2]*dx[2]); if(elen != 0.) { dx[0] /= elen; dx[1] /= elen; dx[2] /= elen; } oktang = 1; for(j = 0; j < 2; j++) { fl = dx[0]*tv[j][0] + dx[1]*tv[j][1] + dx[2]*tv[j][2]; if(fl < 0.) { tv[j][0] *= -1.; tv[j][1] *= -1.; tv[j][2] *= -1.; } if(fabs(fl) < .5) { oktang = 0; break; } } if(oktang) { vis_SurfMeshSetTriTang (surfmesh,elemind,i+1,tv); } } } /* tag for nodes and elements generated on geometry face */ if(face_id) { vis_SurfMeshSetTriBack (surfmesh,elemind,rfaceflag,lfaceflag); if(rfaceid) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,elemind, SYS_ELEM,0,rfaceid); /* add VIS_PROPID for NASTRAN bulk data file export */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,elemind, SYS_ELEM,0,rfaceid); } if(lfaceid) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,elemind, SYS_ELEM,-1,lfaceid); /* add VIS_PROPID for NASTRAN bulk data file export */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,elemind, SYS_ELEM,-1,lfaceid); } vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,elemind,SYS_FACE,0, face_id); if(hasconic) { vis_SurfMeshSetTriConic (surfmesh,elemind,conicid); } } } }; static void process_wires(ENTITY_LIST *wires, vis_CurvMesh *curvmesh) { bool again; Vint numnp, numel, ix[2], index; Vdouble x[3]; vsy_IntHash *nodeih; tag_id_type id, start_tag, end_tag; nodeih = vsy_IntHashBegin (); numnp = numel = 0; if (wires->count()) { WIRE* wire = (WIRE*)wires->first(); while (wire) { if (wire->cont() == ALL_INSIDE) { ENTITY_LIST edges; check_outcome(api_get_edges(wire,edges)); if (edges.count()) { EDGE* edge = (EDGE*)edges.first(); while (edge) { api_get_entity_id((ENTITY*)edge,id); id += 1; VERTEX* start = edge->start(); VERTEX* end = edge->end(); /* get entity tags and offset by 1 */ api_get_entity_id((ENTITY*)start,start_tag); start_tag += 1; api_get_entity_id((ENTITY*)end,end_tag); end_tag += 1; AF_POINT *de0; AF_POINT *deN; AF_POINT *de; if (AF_POINT::find( edge, edge->sense(), de0, deN)) { Vdouble ts[2][3]; de = de0; again = true; do { double t = de->get_parameter(); SPAposition p = de->get_position(); x[0] = p.x(); x[1] = p.y(); x[2] = p.z(); SPAvector tan_vec = edge->geometry()->equation().eval_deriv(t,TRUE,TRUE); SPAunit_vector tang = normalise (tan_vec); if(de == de0) { ts[0][0] = tang.x(); ts[0][1] = tang.y(); ts[0][2] = tang.z(); vsy_IntHashLookup (nodeih,start_tag,&index); if(index == 0) { index = ++numnp; vsy_IntHashInsert (nodeih,start_tag,index); vis_CurvMeshSetPoint (curvmesh,index,x,1); vis_CurvMeshSetPointAssoc (curvmesh, VIS_GEOVERT,index, start_tag); } ix[0] = index; } else if(de == deN) { vsy_IntHashLookup (nodeih,end_tag,&index); if(index == 0) { index = ++numnp; vsy_IntHashInsert (nodeih,end_tag,index); vis_CurvMeshSetPoint (curvmesh,index,x,1); vis_CurvMeshSetPointAssoc (curvmesh, VIS_GEOVERT,index, end_tag); } again = false; ix[1] = index; ++numel; vis_CurvMeshSetLine (curvmesh,numel,ix); ts[1][0] = tang.x(); ts[1][1] = tang.y(); ts[1][2] = tang.z(); vis_CurvMeshSetLineTang (curvmesh,numel,ts); vis_CurvMeshSetLineAssoc (curvmesh,VIS_GEOEDGE, numel,id); /* save information for next point */ ix[0] = ix[1]; ts[0][0] = ts[1][0]; ts[0][1] = ts[1][1]; ts[0][2] = ts[1][2]; } else { index = ++numnp; vis_CurvMeshSetPoint (curvmesh,index,x,1); ix[1] = index; ++numel; vis_CurvMeshSetLine (curvmesh,numel,ix); ts[1][0] = tang.x(); ts[1][1] = tang.y(); ts[1][2] = tang.z(); vis_CurvMeshSetLineTang (curvmesh,numel,ts); vis_CurvMeshSetLineAssoc (curvmesh,VIS_GEOEDGE, numel,id); /* save information for next point */ ix[0] = ix[1]; ts[0][0] = ts[1][0]; ts[0][1] = ts[1][1]; ts[0][2] = ts[1][2]; } de = de->next(0); } while(again); } edge = (EDGE*)edges.next(); } } } wire = (WIRE*)wires->next(); } } vsy_IntHashEnd (nodeih); } static void count_wire_ents(ENTITY_LIST *wires, Vint *numnodes, Vint *numsegs) { bool again; Vint numnp, numel, index; vsy_IntHash *nodeih; tag_id_type start_tag, end_tag; *numnodes = *numsegs = 0; numnp = numel = 0; nodeih = vsy_IntHashBegin (); if (wires->count()) { WIRE* wire = (WIRE*)wires->first(); while (wire) { if (wire->cont() == ALL_INSIDE) { ENTITY_LIST edges; check_outcome(api_get_edges(wire,edges)); if (edges.count()) { EDGE* edge = (EDGE*)edges.first(); while (edge) { VERTEX* start = edge->start(); VERTEX* end = edge->end(); /* get entity tags and offset by 1 */ api_get_entity_id((ENTITY*)start,start_tag); start_tag += 1; api_get_entity_id((ENTITY*)end,end_tag); end_tag += 1; AF_POINT *de0; AF_POINT *deN; AF_POINT *de; if (AF_POINT::find( edge, edge->sense(), de0, deN)) { de = de0; again = true; do { if(de == de0) { vsy_IntHashLookup (nodeih,start_tag,&index); if(index == 0) { index = ++numnp; vsy_IntHashInsert (nodeih,start_tag,index); } } else if(de == deN) { vsy_IntHashLookup (nodeih,end_tag,&index); if(index == 0) { index = ++numnp; vsy_IntHashInsert (nodeih,end_tag,index); } again = false; ++numel; } else { ++numnp; ++numel; } de = de->next(0); } while(again); } edge = (EDGE*)edges.next(); } } } wire = (WIRE*)wires->next(); } } vsy_IntHashEnd (nodeih); *numnodes = numnp; *numsegs = numel; } /*---------------------------------------------------------------------- Illustrate ACIS Interface to CurvMesh, SurfMesh and TetMesh ----------------------------------------------------------------------*/ int main(int argc, char *argv[]) { ENTITY_LIST ents; ENTITY *ent; vis_Connect *connect; vis_Connect *connectsrf; vis_Connect *connecttet; vis_Connect *connectcrv; vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vis_CurvMesh *curvmesh; outcome res; Vint maxi; Vint numpnts, numtris; Vint i; Vint numnp, numel; Vint pflag; Vint nfree; Vdouble diaglen, edgelen; Vdouble minext[3], maxext[3]; Vdouble x[3]; FILE *fsat; REFINEMENT *ref; int enttype; Vint ibody; Vint ierr; Vchar filnam[256]; Vint tetmeshoption; Vint numwirepnts, numwiresegs; if(argc < 2) { printf("Usage: %s acis_sat_file\n",argv[0]); return 0; } /* * function to call in order to unlock the spatial products. * SPATIAL_LICENSE is defined in spatial_license.h and points to the license key string. */ spa_unlock_result out = spa_unlock_products( SPATIAL_LICENSE ); if ( out.get_state() != SPA_UNLOCK_PASS && out.get_state() != SPA_UNLOCK_PASS_WARN) { printf("%s\n",out.get_message_text()); return 0; } /* initialize ACIS */ init_acis(); /* open ACIS sat file */ fsat = acis_fopen(argv[1],"r"); if(fsat == NULL) { printf("Unable to open sat file %s\n",argv[1]); return -1; } /* GHF */ printf("acis_fopen\n"); /* restore the entities within */ res = api_restore_entity_list(fsat,TRUE,ents); check_outcome(res); /* GHF */ printf("api_restore_entity_list\n"); /* ACIS sat file */ acis_fclose(fsat); /* GHF */ printf("acis_fclose\n"); /* create a refinement object */ res = api_create_refinement(ref); /* GHF */ printf("A api_create_refinement\n"); check_outcome(res); /* GHF */ printf("B api_create_refinement\n"); /* a normal tolerance of 15 degrees */ API_BEGIN ref->set_normal_tol(15); API_END EXCEPTION_BEGIN MESH_MANAGER* old_MM = NULL; MESH_MANAGER* MM = NULL; EXCEPTION_TRY /* instance surface mesher and tet mesher objects */ surfmesh = vis_SurfMeshBegin (); tetmesh = vis_TetMeshBegin (); /* instance Connect object to hold resultant mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); check_outcome (api_get_mesh_manager(old_MM)); /* create and install VKI mesh manager */ MM = ACIS_NEW VKI_MESH_MANAGER(surfmesh); res = api_set_mesh_manager(MM); check_outcome(res); /* mesh each body separately */ ibody = 0; for(ents.init(); (ent = ents.next());) { ibody += 1; #ifdef VKI_PROJECT_WIRES ENTITY_LIST wires; #endif /* use no-op block to rollback body transformation */ API_NOP_BEGIN api_change_body_trans((BODY*)ent,NULL); enttype = ent->identity(); res = api_set_entity_refinement(ent,ref,FALSE); check_outcome(res); /* facet entity */ res = api_facet_entity(ent); check_outcome(res); /* wire entity */ #ifdef VKI_PROJECT_WIRES res = api_get_wires(ent,wires); check_outcome(res); count_wire_ents (&wires,&numwirepnts,&numwiresegs); if(numwirepnts && numwiresegs) { curvmesh = vis_CurvMeshBegin (); vis_CurvMeshDef (curvmesh,numwirepnts,numwiresegs); process_wires (&wires,curvmesh); } #endif API_NOP_END check_outcome(result); /* find extent of object to set a reasonable element size */ vis_SurfMeshInq (surfmesh,&numpnts,&numtris); if(numpnts == 0 || numtris == 0) continue; printf(" Tesselation number of points= %d\n", numpnts); printf(" Tesselation number of tris= %d\n", numtris); for(i = 1; i <= numpnts; i++) { vis_SurfMeshGetPoint (surfmesh,i,x,&pflag); if(i == 1) { minext[0] = maxext[0] = x[0]; minext[1] = maxext[1] = x[1]; minext[2] = maxext[2] = x[2]; } else { if(x[0] < minext[0]) minext[0] = x[0]; if(x[1] < minext[1]) minext[1] = x[1]; if(x[2] < minext[2]) minext[2] = x[2]; if(x[0] > maxext[0]) maxext[0] = x[0]; if(x[1] > maxext[1]) maxext[1] = x[1]; if(x[2] > maxext[2]) maxext[2] = x[2]; } } diaglen = sqrt( (maxext[0]-minext[0])*(maxext[0]-minext[0]) + (maxext[1]-minext[1])*(maxext[1]-minext[1]) + (maxext[2]-minext[2])*(maxext[2]-minext[2]) ); /* set element size to 10% of diagonal of extent box */ edgelen = diaglen/10.; vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelen); maxi = 3; /* generate CurvMesh */ #ifdef VKI_PROJECT_WIRES if(numwirepnts && numwiresegs) { vis_CurvMeshSetParami (curvmesh,VIS_MESH_MAXI,maxi); vis_CurvMeshSetParamd (curvmesh,VIS_MESH_EDGELENGTH,edgelen); connectcrv = vis_ConnectBegin (); vis_ConnectDef (connectcrv,0,0); vis_ConnectPre (connectcrv,SYS_DOUBLE); /* optional write of CurvMesh contents for QA sprintf(filnam,"exam52acis%d.crv",ibody); vis_CurvMeshWrite (curvmesh,SYS_ASCII,filnam); */ vis_CurvMeshGenerate (curvmesh,connectcrv); vis_CurvMeshEnd (curvmesh); /* vertices and elements are now those in the generated mesh */ vis_ConnectNumber (connectcrv,SYS_NODE,&numwirepnts); vis_ConnectNumber (connectcrv,SYS_ELEM,&numwiresegs); /* optional write of mesh sprintf(filnam,"model-crv%d.unv",ibody); vis_ConnectWrite (connectcrv, SYS_SDRC_UNIVERSAL,filnam); */ } #endif vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.01*edgelen); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_GROWTHRATE,2.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,30.); /* generate parabolic triangles */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,maxi); /* enable non-manifold geometries */ vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,SYS_ON); /* double backed triangulation for internal surfaces */ vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,SYS_ON); connectsrf = vis_ConnectBegin (); vis_ConnectDef (connectsrf,0,0); vis_ConnectPre (connectsrf,SYS_DOUBLE); /* set exact geometry projection callback vis_SurfMeshSetFunction (surfmesh,SURFMESH_FUN_GEOPROJ, (Vfunc*)project_surfmesh2acis,NULL); */ /* optional write of SurfMesh contents for QA */ sprintf(filnam,"exam52acis%d.srf",ibody); vis_SurfMeshWrite (surfmesh,SYS_ASCII,filnam); vis_SurfMeshGenerate (surfmesh,connectsrf); ierr = vis_SurfMeshError (surfmesh); if(ierr) { printf("Error generating surface mesh, body= %d\n",ibody); sprintf(filnam,"model-%d.srf",ibody); vis_SurfMeshWrite (surfmesh,SYS_ASCII,filnam); continue; } /* add curve mesh to surface mesh */ #ifdef VKI_PROJECT_WIRES if(numwirepnts && numwiresegs) { vis_ConnectAppend (connectsrf,connectcrv); vis_ConnectMerge (connectsrf,NULL); vis_ConnectEnd (connectcrv); } #endif printf("SurfMesh body= %d complete\n",ibody); vis_ConnectNumber (connectsrf, SYS_NODE, &numnp); vis_ConnectNumber (connectsrf, SYS_ELEM, &numel); printf(" Surface number of nodes= %d\n", numnp); printf(" Surface number of elems= %d\n", numel); /* optional write of surface mesh sprintf(filnam,"model-srf%d.bdf",ibody); vis_ConnectWrite (connectsrf,SYS_NASTRAN_BULKDATA,filnam); */ tetmeshoption = 0; /* test for no free edges */ vis_SurfMeshGetInteger (surfmesh,SURFMESH_NUMFREEEDGE,&nfree); if(nfree) { tetmeshoption = 0; } if(tetmeshoption) { connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); /* add surface mesh information to tetmesh */ vis_TetMeshConnect (tetmesh,connectsrf); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,edgelen); vis_TetMeshSetParamd (tetmesh,VIS_MESH_GROWTHRATE,2.); /* optional write of TetMesh contents for QA sprintf(filnam,"model_%d.btet",ibody); vis_TetMeshWrite (tetmesh,SYS_BINARY,filnam); */ vis_TetMeshGenerate (tetmesh,connecttet); ierr = vis_TetMeshError (tetmesh); if(ierr) { printf("Error generating tet mesh, volume= %d\n",ibody); sprintf(filnam,"model_%d.btet",ibody); vis_TetMeshWrite (tetmesh,SYS_BINARY,filnam); vis_ConnectEnd (connecttet); continue; } printf("TetMesh body= %d complete\n",ibody); vis_ConnectNumber (connecttet, SYS_NODE, &numnp); vis_ConnectNumber (connecttet, SYS_ELEM, &numel); printf(" Volume number of nodes= %d\n", numnp); printf(" Volume number of elems= %d\n", numel); /* optional write of volume mesh sprintf(filnam,"model-tet%d.bdf",ibody); vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA,filnam); */ vis_ConnectAppend (connect,connecttet); vis_ConnectEnd (connecttet); } else { vis_ConnectAppend (connect,connectsrf); } } /* report total number of generate nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("total number of nodes= %d\n",numnp); printf("total number of elems= %d\n",numel); /* optional write of final mesh */ if(numnp && numel) { vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"model-tet.bdf"); vis_ConnectWrite (connect,SYS_SDRC_UNIVERSAL,"model-tet.unv"); } /* clean up */ vis_SurfMeshEnd (surfmesh); vis_TetMeshEnd (tetmesh); vis_ConnectEnd (connect); ref->lose(); EXCEPTION_CATCH_TRUE api_set_mesh_manager (old_MM); ACIS_DELETE MM; EXCEPTION_END /* final cleanup */ res = api_del_entity_list(ents); check_outcome(res); term_acis(); return 0; }
#include "base/base.h" #include "vis/vis.h" #include "vis/vismesh.h" #include "capri.h" /* SurfMesh geometry projection callback function */ void project_surfmesh2capri(vis_SurfMesh *surfmesh, Vobject *object, Vint enttype, Vint entaid, Vdouble uh[], Vdouble xh[3], Vdouble ug[], Vdouble xg[3]) { Vint *ivol = (Vint*)object; Vint status; Vdouble uv[4]; uv[0] = uv[1] = uv[2] = uv[3] = 1.e+20; if(enttype == SYS_EDGE) { status = gi_qNearestOnEdge(*ivol,entaid,xh,uv,xg); } else if(enttype == SYS_FACE) { status = gi_qNearestOnFace(*ivol,entaid,xh,uv,xg); } if(status) { xg[0] = xh[0]; xg[1] = xh[1]; xg[2] = xh[2]; } } /* utility function to transform a point */ static void transform(Vdouble tm[3][4], Vdouble point[], Vdouble out[]) { out[0] = tm[0][0]*point[0] + tm[0][1]*point[1] + tm[0][2]*point[2] + tm[0][3]; out[1] = tm[1][0]*point[0] + tm[1][1]*point[1] + tm[1][2]*point[2] + tm[1][3]; out[2] = tm[2][0]*point[0] + tm[2][1]*point[1] + tm[2][2]*point[2] + tm[2][3]; } /* load CAPRI tesselation of a volume into SurfMesh */ static void loadvolume(Vint ivol, vis_SurfMesh *surfmesh) { vsy_IntDict *intdict; vis_IdTran *idtran; Vint status,i,j,k; Vint no, aid; Vchar *name, buf[256]; Vint nnode,nedge,nface,nbound,n; Vint iface; Vdouble tm[3][4],*points,*uv, x[3], vn[3][3]; Vint tlen,*tris,*tric,plen,*ptype,*pindex; Vint numnp,numel,ix[3],jx[3],efl[3],base,npts; Vint iszero; Vint nedgept, n1, n2, nodes[2]; Vdouble *edgept, *edget, trange[2], tang[2][3], curv; status = gi_dGetVolume (ivol,&nnode,&nedge,&nface,&nbound,&name); if(status) { printf("Error reading volume information for volume= %d\n",ivol); return; } printf("Loaded volume= %s\n",name); status = gi_iGetDisplace (ivol,(double*)tm); if(status) { printf("Error reading Displace for volume= %d\n",ivol); return; } intdict = vsy_IntDictBegin (); idtran = vis_IdTranBegin (); /* count total number of tesselation points and triangles */ numnp = numel = npts = 0; for(iface = 1; iface <= nface; ++iface) { status = gi_dTesselFace (ivol,iface,&tlen,&tris,&tric,&plen,&points, &ptype,&pindex,&uv); if(status) { printf("Error reading TesselFace for volume= %d, face= %d\n", ivol,iface); return; } /* loop through points on tesselated face */ for(i = 0; i < plen; ++i) { /* encode edge flag and point */ sprintf(buf,"%d %d",ptype[i],pindex[i]); /* if node in interior */ if(ptype[i] == -1) { numnp += 1; vsy_IntDictInsert (intdict,buf,numnp); n = numnp; /* node not in interior */ } else { vsy_IntDictLookup (intdict,buf,&n); if(n == 0) { numnp += 1; vsy_IntDictInsert (intdict,buf,numnp); n = numnp; } } npts += 1; vis_IdTranSetId (idtran,npts,n); } numel += tlen; } vsy_IntDictEnd (intdict); vis_SurfMeshDef (surfmesh,numnp,numel); npts = base = numel = 0; for(iface = 1; iface <= nface; ++iface) { status = gi_dTesselFace (ivol,iface,&tlen,&tris,&tric,&plen,&points, &ptype,&pindex,&uv); if(status) { printf("Error reading TesselFace for volume= %d, face= %d\n", ivol,iface); return; } /* loop through points on tesselated face */ for(i = 0; i < plen; ++i) { npts += 1; vis_IdTranGetId (idtran,npts,&n); transform (tm,&points[3*i],x); /* if node in interior */ if(ptype[i] == -1) { vis_SurfMeshSetPoint (surfmesh,n,x,0); /* if node not in interior, ie on edge/vertex */ } else { /* node on geometry vertex */ if(ptype[i] == 0) { vis_SurfMeshSetPoint (surfmesh,n,x,1); vis_SurfMeshSetPointAssoc(surfmesh,VIS_GEOVERT,n,pindex[i]); /* node on geometry edge, not on vertex */ } else { vis_SurfMeshSetPoint (surfmesh,n,x,0); } } } /* loop through triangles on tesselated face */ for(i = 0; i < tlen; ++i) { numel += 1; ix[0] = tris[3*i ] + base; ix[1] = tris[3*i+1] + base; ix[2] = tris[3*i+2] + base; vis_IdTranGetIds (idtran,3,ix,jx); /* flag triangle edges on geometry edges */ for(j = 0; j < 3; ++j) { k = (j+1)%3; efl[k] = 0; if(tric[3*i+j] < 0) { efl[k] = 1; } } vis_SurfMeshSetTri (surfmesh,numel,jx,efl); vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,numel,SYS_FACE,1,iface); vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,numel,SYS_ELEM,1,ivol); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,numel,SYS_ELEM,1,ivol); iszero = 0; /* loop over triangle nodes */ for(j = 0; j < 3; ++j) { if(tric[3*i+j] < 0) { /* edge number opposing node */ no = (j+1)%3+1; /* edge association is geometry edge number */ aid = -tric[3*i+j]; vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,numel,SYS_EDGE, no,aid); /* set triangle edge tangents */ status = gi_dTesselEdge (ivol,aid,&nedgept,&edgept,&edget); n1 = tris[3*i+(j+1)%3]-1; n2 = tris[3*i+(j+2)%3]-1; ix[0] = ptype[n1]; ix[1] = ptype[n2]; /* point on edge information not available */ gi_dGetEdge (ivol,aid,trange,nodes); if(ix[0] == 0) { if(pindex[n1] == nodes[0]) { ix[0] = 1; } else { ix[0] = nedgept; } } if(ix[1] == 0) { if(pindex[n2] == nodes[0]) { ix[1] = 1; } else { ix[1] = nedgept; } } --ix[0]; --ix[1]; status = gi_cCurvOfEdge (ivol,aid,edget[ix[0]],tang[0],&curv); status = gi_cCurvOfEdge (ivol,aid,edget[ix[1]],tang[1],&curv); if(edget[ix[1]]-edget[ix[0]] < 0.) { tang[0][0] = -tang[0][0]; tang[0][1] = -tang[0][1]; tang[0][2] = -tang[0][2]; tang[1][0] = -tang[1][0]; tang[1][1] = -tang[1][1]; tang[1][2] = -tang[1][2]; } vis_SurfMeshSetTriTang (surfmesh,numel,no,tang); } /* evaluate normal at node, check for zeros */ status = gi_qNormalToFace (ivol,iface,&uv[2*tris[3*i+j]-2],x,vn[j]); if(vn[j][0] == 0. && vn[j][1] == 0. && vn[j][2] == 0.) { iszero = 1; } } /* set triangle node normals */ if(!iszero) { vis_SurfMeshSetTriNorm (surfmesh,numel,vn); } } base += plen; } vis_IdTranEnd (idtran); } /*---------------------------------------------------------------------- Illustrate CAPRI Interface to SurfMesh and TetMesh ----------------------------------------------------------------------*/ int main(int argc, char *argv[]) { Vint i; vis_Connect *connectsrf, *connecttet, *connect; vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; Vint imodel, status, nvol, ivol, icode; Vint ierr; Vint numpnts, numtris; Vint numnp, numel; Vchar buf[256]; Vdouble extent[2][3], dmax, d, edgelen; if(argc < 3) { printf("Usage: %s modeller model\n",argv[0]); return 1; } status = gi_uStart(); if(status) { printf("Unable to start CAPRI\n"); return 1; } printf("CAPRI started\n"); gi_putenv("CAPRItess=On"); imodel = gi_uLoadModel (NULL,argv[1],argv[2]); if(imodel == 0) { printf("Unable to open %s model %s\n",argv[1],argv[2]); return 1; } printf("CAPRI model loaded\n"); /* get number of volumes */ nvol = gi_uNumVolumes(); /* get maximum extent of all volumes */ dmax = 0.; for(ivol = 1; ivol <= nvol; ++ivol) { icode = gi_dBox(ivol,(double*)extent); for(i = 0; i < 3; ++i) { d = extent[1][i]-extent[0][i]; if(d > dmax) dmax = d; } } edgelen = dmax/20.; /* instance surface mesher and tet mesher */ surfmesh = vis_SurfMeshBegin (); tetmesh = vis_TetMeshBegin (); /* instance Connect object to hold resultant mesh */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); /* mesh each volume separately */ for(ivol = 1; ivol <= nvol; ++ivol) { connectsrf = vis_ConnectBegin (); vis_ConnectPre (connectsrf,SYS_DOUBLE); vis_SurfMeshSetFunction (surfmesh,SURFMESH_FUN_GEOPROJ, (Vfunc*)project_surfmesh2capri,(Vobject*)&ivol); /* load the CAPRI geometry tesselation into SurfMesh */ loadvolume (ivol,surfmesh); vis_SurfMeshInq (surfmesh,&numpnts,&numtris); if(numpnts == 0 || numtris == 0) continue; /* compute extent to set reasonable mesh size */ vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelen); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,45.); /* generate parabolic triangles */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam52capri.srf"); vis_SurfMeshGenerate (surfmesh,connectsrf); ierr = vis_SurfMeshError (surfmesh); if(ierr) { printf("Error generating surface mesh, volume= %d\n",ivol); sprintf(buf,"model_%d.srf",ivol); vis_SurfMeshWrite (surfmesh,SYS_ASCII,buf); vis_ConnectEnd (connectsrf); continue; } printf("SurfMesh volume= %d complete\n",ivol); icode = gi_dVolumeType(ivol); /* volume is solid, generate tet mesh */ if(icode == 0) { connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_TetMeshConnect (tetmesh,connectsrf); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,edgelen); vis_TetMeshGenerate (tetmesh,connecttet); ierr = vis_TetMeshError (tetmesh); if(ierr) { printf("Error generating tet mesh, volume= %d\n",ivol); sprintf(buf,"model_%d.tet",ivol); vis_TetMeshWrite (tetmesh,SYS_ASCII,buf); vis_ConnectEnd (connecttet); continue; } printf("TetMesh volume= %d complete\n",ivol); vis_ConnectAppend (connect,connecttet); vis_ConnectEnd (connecttet); /* volume is shell */ } else { vis_ConnectAppend (connect,connectsrf); } vis_ConnectEnd (connectsrf); } /* report total number of generate nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("total number of nodes= %d\n",numnp); printf("total number of elems= %d\n",numel); if(numnp && numel) { vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam52capri.bdf"); } /* clean up */ vis_SurfMeshEnd (surfmesh); vis_TetMeshEnd (tetmesh); vis_ConnectEnd (connect); status = gi_uRelModel (imodel); status = gi_uStop(0); return 0; }
/*********************************************************************** * * * Copyright (C) 2011, Visual Kinematics, Inc. * * * * These coded inttructions, statements and computer programs contain * * unpublished proprietary information of Visual Kinematics, Inc., * * and are protected by Federal copyright law. They may not be * * disclosed to third parties or copied or duplicated in any form, * * in whole or in part, without the prior written consent of * * Visual Kinematics, Inc. * * * ***********************************************************************/ /* file : exam52pk.cxx description: Parasolid PK file library object author : Arthur Muller date : May 5, 2011 discussion : */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "base/base.h" #include "base/vututil.h" #include "vis/vis.h" #include "vis/vismesh.h" /* * The three files below are part of the * Parasolid installation */ #include "parasolid_kernel.h" #include "frustrum_ifails.h" #include "frustrum_tokens.h" /* * The frustrum functions below are required by * the Parasolid engine. We use the example frustrum * functions provided with the Parasolid distribution, * located, in the Windows installation, in * * Parasolid\Parasolid Jumpstart Kit\ * example_applications\C++\Code Examples\ * Application Support\Downward Interfaces\Frustrum */ #include "frustrum.cpp" /* * The static variables below * are required by the Parasolid engine */ static PK_SESSION_frustrum_t frustrum; static PK_ERROR_frustrum_t errorFrustrum; static PK_SESSION_start_o_t options; /* * The error handler and memory allocation functions * are required by the Parasolid engine */ extern PK_ERROR_code_t parasolid_ErrorHandler(PK_ERROR_sf_t *error) { printf("PK error: %s returned %s\n", error->function,error->code_token); return error->code; } extern void parasolid_ReturnMemory(int *nbytes, char **memory, int *ifail) { vut_freeMem (*memory); *ifail = FR_no_errors; } extern void parasolid_GetMemory(int *nbytes, char **memory, int *ifail) { *ifail = FR_no_errors; *memory = (Vchar*)vut_mallocMem(*nbytes); if(*memory == NULL) { *ifail = FR_memory_full; } } static void parasolid_Init() { /* initialize frustrum with default values */ errorFrustrum.handler_fn = parasolid_ErrorHandler; PK_SESSION_frustrum_o_m(frustrum); frustrum.fstart = StartFileFrustrum; frustrum.fstop = StopFileFrustrum; frustrum.ffoprd = OpenReadFrustrumFile; frustrum.ffopwr = OpenWriteFrustrumFile; frustrum.ffwrit = WriteToFrustrumFile; frustrum.ffread = ReadFromFrustrumFile; frustrum.ffclos = CloseFrustrumFile; frustrum.fabort = AbortFrustrum; frustrum.fmallo = parasolid_GetMemory; frustrum.fmfree = parasolid_ReturnMemory; /* register frustrum */ PK_SESSION_register_frustrum (&frustrum); /* start the modeller */ PK_SESSION_start_o_m(options); PK_SESSION_start(&options); } static void parasolid_Term() { PK_SESSION_stop(); } static Vint writesurfmesh = 1; /*---------------------------------------------------------------------- Illustrate Parasolid x_t/x_b interface to SurfMesh ----------------------------------------------------------------------*/ int main(int argc, char *argv[]) { /* DevTools interface definitions */ vis_SurfMesh *surfmesh; vis_TetMesh *tetmesh; vsy_IntHash *nodeih; vsy_IntHash *vertexih; vis_Connect *connectsrf, *connect, *connecttet; vsy_IntHash *bodylih, *bodyrih, *conicih; vsy_IntHash *finedgeih; vsy_IntHash *pointvertexih; vsy_IntVec *faceorientiv; Vint nparts, geobody, geobodyrb, geobodylb; Vint ii, j, m, finID, finIndex, point, normalIndex, facetID, geoface; Vint geoedge[3], geovert[3]; Vint length, ix[3], index; Vint conicid, numconic, isconic; Vdouble *xl, *xn, vertex[3][3], normals[3][3]; Vdouble xo[3], axis[3], ref[3], cr, cc; Vint numel, numnp, eflags[3], sense; Vchar buffer[256]; Vdouble minext[3], maxext[3], diaglen, edgelen; int n_vertices, n_regions, n_shells, isvoid, n_faces; double t, tang[2][3], etang[3]; Vint ierr, tetmeshoption, nfree; Vchar filnam[256]; /* Parasolid interface definitions */ PK_PART_t *parts; PK_TOPOL_fctab_facet_fin_s *facet_fin; PK_TOPOL_fctab_fin_fin_s *fin_fin; PK_TOPOL_fctab_fin_data_s *fin_data; PK_TOPOL_fctab_data_point_s *data_point_idx; PK_TOPOL_fctab_data_normal_s *data_normal_idx; PK_TOPOL_fctab_point_vec_s *point_vec; PK_TOPOL_fctab_normal_vec_s *normal_vec; PK_TOPOL_fctab_facet_face_s *facet_face; PK_TOPOL_fctab_fin_edge_s *fin_edge; PK_TOPOL_fctab_point_topol_s *point_topol; PK_VERTEX_t *vertices; PK_REGION_t *regions; PK_SHELL_t *shells; PK_FACE_t *faces; PK_LOGICAL_t *orients, orientf; PK_ERROR_t err = PK_ERROR_no_errors; PK_PART_receive_o_t receive_opts; PK_CLASS_t eclass, sclass; PK_BODY_type_t bodyType; PK_TOPOL_facet_2_r_t tables; PK_TOPOL_facet_2_o_t facetOptions; PK_GEOM_range_vector_o_t options; PK_range_result_t range_result; PK_range_1_r_t range; PK_LOGICAL_t is_solid; PK_SURF_t surf; PK_CURVE_t curve; PK_VECTOR_t pt, tg; if(argc < 2) { fprintf(stderr,"Usage: %s parasolid_x_t_file\n",argv[0]); return 0; } nparts = 0; parts = NULL; numnp = numel = 0; /* open Parasolid file */ PK_PART_receive_o_m (receive_opts); if(strstr(argv[1],".x_t") || strstr(argv[1],".xmt_txt")) { receive_opts.transmit_format = PK_transmit_format_text_c; } else if(strstr(argv[1],".x_b") || strstr(argv[1],".xmt_bin")) { receive_opts.transmit_format = PK_transmit_format_binary_c; } else { fprintf(stderr,"Unknown file extension\n"); return 1; } /* initialize Parasolid engine */ parasolid_Init(); /* load Parasolid parts */ err = PK_PART_receive (argv[1],&receive_opts,&nparts,&parts); if(err != PK_ERROR_no_errors) { fprintf(stderr,"PK_PART_receive error= %d\n",err); return 1; } /* set default Parasolid tesselation options */ PK_TOPOL_facet_2_o_m(facetOptions); /* set default Parasolid point projection options */ PK_GEOM_range_vector_o_m(options); /* initialize DevTools objects */ surfmesh = vis_SurfMeshBegin (); tetmesh = vis_TetMeshBegin (); connect = vis_ConnectBegin(); vis_ConnectPre (connect,SYS_DOUBLE); vertexih = vsy_IntHashBegin (); /* initialize tesselation choice options */ facetOptions.choice.facet_fin = true; facetOptions.choice.fin_data = true; facetOptions.choice.data_point_idx = true; facetOptions.choice.data_normal_idx = true; facetOptions.choice.point_vec = true; facetOptions.choice.normal_vec = true; facetOptions.choice.facet_face = true; facetOptions.choice.fin_edge = true; facetOptions.choice.point_topol = true; facetOptions.choice.facet_fin = PK_LOGICAL_true; facetOptions.choice.fin_fin = PK_LOGICAL_true; facetOptions.choice.fin_data = PK_LOGICAL_true; facetOptions.choice.data_point_idx = PK_LOGICAL_true; facetOptions.choice.data_normal_idx = PK_LOGICAL_true; facetOptions.choice.point_vec = PK_LOGICAL_true; facetOptions.choice.normal_vec = PK_LOGICAL_true; facetOptions.choice.facet_face = PK_LOGICAL_true; facetOptions.choice.fin_edge = PK_LOGICAL_true; facetOptions.choice.point_topol = PK_LOGICAL_true; /* initialize tesselation control options */ facetOptions.control.shape = PK_facet_shape_convex_c; facetOptions.control.match = PK_facet_match_topol_c; /* * The option below is used to minimize the number * of edge tesselation point that are not on the edge */ facetOptions.control.quality = PK_facet_quality_improved_c; /* loop over all parts */ for(int i = 0; i < nparts; i++) { PK_ENTITY_ask_class(parts[i],&eclass); if(eclass == PK_CLASS_body) { /* initialize IntHash for body to the left of face */ bodylih = vsy_IntHashBegin (); bodyrih = vsy_IntHashBegin (); conicih = vsy_IntHashBegin (); faceorientiv = vsy_IntVecBegin (); numconic = 0; /* check for solid, sheet, or non-manifold body */ PK_BODY_ask_type (parts[i],&bodyType); if(bodyType == PK_BODY_type_sheet_c || bodyType == PK_BODY_type_solid_c || bodyType == PK_BODY_type_general_c) { if(bodyType == PK_BODY_type_general_c) { vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,SYS_ON); } else { vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,SYS_OFF); } /* create region->face map */ PK_BODY_ask_regions (parts[i],&n_regions,®ions); for(int ir = 0; ir < n_regions; ir++) { /* skip non-solid regions */ PK_REGION_is_solid (regions[ir],&is_solid); if(is_solid == false) { continue; } PK_REGION_ask_shells (regions[ir],&n_shells,&shells); /* * The "isvoid" flag checks whether any face orientation * points outwardly to the body. If all faces point * inwardly SurfMeshGenerate will still succeed. However, * this problem needs to be accounted for when passing * the surface mesh to TetMesh. */ isvoid = 1; for(int is = 0; is < n_shells; is++) { PK_SHELL_ask_oriented_faces (shells[is],&n_faces, &faces,&orients); for(int ifa = 0; ifa < n_faces; ifa++) { if(!orients[ifa]) { vsy_IntHashInsert (bodylih,faces[ifa],regions[ir]); isvoid = 0; } else { vsy_IntHashInsert (bodyrih,faces[ifa],regions[ir]); } PK_FACE_ask_oriented_surf (faces[ifa],&surf,&orientf); PK_ENTITY_ask_class(surf,&sclass); isconic = 0; if(sclass == PK_CLASS_plane) { isconic = sclass; } else if(sclass == PK_CLASS_cyl) { isconic = sclass; } else if(sclass == PK_CLASS_cone) { isconic = sclass; } else if(sclass == PK_CLASS_sphere) { isconic = sclass; } else if(sclass == PK_CLASS_torus) { isconic = sclass; } if(isconic) { vsy_IntHashLookup (conicih,surf,&conicid); if(conicid == 0) { numconic += 1; #ifdef MESH_DEBUG printf("conicid= %d, orientf= %d\n",numconic,orientf); #endif vsy_IntHashInsert (conicih,surf,numconic); vsy_IntVecSet (faceorientiv,numconic,orientf); } } } if(n_faces) { PK_MEMORY_free (faces); PK_MEMORY_free (orients); } } if(n_shells) { PK_MEMORY_free (shells); } } if(n_regions) { PK_MEMORY_free (regions); } /* assign part number to vertices */ numnp = numel = 0; PK_BODY_ask_vertices (parts[i],&n_vertices,&vertices); for(j = 0; j < n_vertices; j++) { vsy_IntHashInsert (vertexih,vertices[j],parts[i]); } if(n_vertices) { PK_MEMORY_free (vertices); } /* tesselate part */ err = PK_TOPOL_facet_2(1,&parts[i],NULL,&facetOptions,&tables); if(err != 0) { fprintf(stderr,"PK_TOPOL_facet_2 error= %d\n",err); return 1; } /* gather tables */ for(j = 0; j < tables.number_of_tables; j++) { if(tables.tables[j].fctab == PK_TOPOL_fctab_facet_fin_c) { facet_fin = tables.tables[j].table.facet_fin; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_fin_fin_c) { fin_fin = tables.tables[j].table.fin_fin; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_fin_data_c) { fin_data = tables.tables[j].table.fin_data; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_data_point_c) { data_point_idx = tables.tables[j].table.data_point_idx; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_data_normal_c) { data_normal_idx = tables.tables[j].table.data_normal_idx; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_point_vec_c) { point_vec = tables.tables[j].table.point_vec; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_normal_vec_c) { normal_vec = tables.tables[j].table.normal_vec; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_facet_face_c) { facet_face = tables.tables[j].table.facet_face; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_fin_edge_c) { fin_edge = tables.tables[j].table.fin_edge; } else if(tables.tables[j].fctab == PK_TOPOL_fctab_point_topol_c) { point_topol = tables.tables[j].table.point_topol; } } /* initialize SurfMesh */ vis_SurfMeshDef (surfmesh,point_vec->length,facet_fin->length/3); /* set conic sections */ vsy_IntHashInitIter (conicih); while(vsy_IntHashNextIter(conicih,&surf,&conicid),conicid) { vsy_IntVecGet (faceorientiv,conicid,&sense); if(sense == 0) sense = -1; #ifdef MESH_DEBUG printf("conicid= %d\n",conicid); #endif PK_ENTITY_ask_class(surf,&sclass); if(sclass == PK_CLASS_plane) { PK_PLANE_sf_t plane_sf; #ifdef MESH_DEBUG printf("PK_CLASS_plane\n"); #endif PK_PLANE_ask (surf,&plane_sf); xo[0] = plane_sf.basis_set.location.coord[0]; xo[1] = plane_sf.basis_set.location.coord[1]; xo[2] = plane_sf.basis_set.location.coord[2]; axis[0] = plane_sf.basis_set.axis.coord[0]; axis[1] = plane_sf.basis_set.axis.coord[1]; axis[2] = plane_sf.basis_set.axis.coord[2]; ref[0] = plane_sf.basis_set.ref_direction.coord[0]; ref[1] = plane_sf.basis_set.ref_direction.coord[1]; ref[2] = plane_sf.basis_set.ref_direction.coord[2]; vis_SurfMeshSetConic (surfmesh,conicid, SURFMESH_CONIC_PLANE,sense,xo,axis,ref,0.,0.); } else if(sclass == PK_CLASS_cyl) { PK_CYL_sf_t cyl_sf; #ifdef MESH_DEBUG printf("PK_CLASS_cyl\n"); #endif PK_CYL_ask (surf,&cyl_sf); xo[0] = cyl_sf.basis_set.location.coord[0]; xo[1] = cyl_sf.basis_set.location.coord[1]; xo[2] = cyl_sf.basis_set.location.coord[2]; axis[0] = cyl_sf.basis_set.axis.coord[0]; axis[1] = cyl_sf.basis_set.axis.coord[1]; axis[2] = cyl_sf.basis_set.axis.coord[2]; ref[0] = cyl_sf.basis_set.ref_direction.coord[0]; ref[1] = cyl_sf.basis_set.ref_direction.coord[1]; ref[2] = cyl_sf.basis_set.ref_direction.coord[2]; cr = cyl_sf.radius; vis_SurfMeshSetConic (surfmesh,conicid, SURFMESH_CONIC_CYLINDER,sense,xo,axis,ref,cr,0.); } else if(sclass == PK_CLASS_cone) { PK_CONE_sf_t cone_sf; #ifdef MESH_DEBUG printf("PK_CLASS_cone\n"); #endif PK_CONE_ask (surf,&cone_sf); xo[0] = cone_sf.basis_set.location.coord[0]; xo[1] = cone_sf.basis_set.location.coord[1]; xo[2] = cone_sf.basis_set.location.coord[2]; axis[0] = cone_sf.basis_set.axis.coord[0]; axis[1] = cone_sf.basis_set.axis.coord[1]; axis[2] = cone_sf.basis_set.axis.coord[2]; ref[0] = cone_sf.basis_set.ref_direction.coord[0]; ref[1] = cone_sf.basis_set.ref_direction.coord[1]; ref[2] = cone_sf.basis_set.ref_direction.coord[2]; cr = cone_sf.semi_angle; vis_SurfMeshSetConic (surfmesh,conicid, SURFMESH_CONIC_CONE,sense,xo,axis,ref,cr,0.); } else if(sclass == PK_CLASS_sphere) { PK_SPHERE_sf_t sphere_sf; #ifdef MESH_DEBUG printf("PK_CLASS_sphere\n"); #endif PK_SPHERE_ask (surf,&sphere_sf); xo[0] = sphere_sf.basis_set.location.coord[0]; xo[1] = sphere_sf.basis_set.location.coord[1]; xo[2] = sphere_sf.basis_set.location.coord[2]; axis[0] = sphere_sf.basis_set.axis.coord[0]; axis[1] = sphere_sf.basis_set.axis.coord[1]; axis[2] = sphere_sf.basis_set.axis.coord[2]; ref[0] = sphere_sf.basis_set.ref_direction.coord[0]; ref[1] = sphere_sf.basis_set.ref_direction.coord[1]; ref[2] = sphere_sf.basis_set.ref_direction.coord[2]; cr = sphere_sf.radius; vis_SurfMeshSetConic (surfmesh,conicid, SURFMESH_CONIC_SPHERE,sense,xo,axis,ref,cr,0.); } else if(sclass == PK_CLASS_torus) { PK_TORUS_sf_t torus_sf; #ifdef MESH_DEBUG printf("PK_CLASS_torus\n"); #endif PK_TORUS_ask (surf,&torus_sf); xo[0] = torus_sf.basis_set.location.coord[0]; xo[1] = torus_sf.basis_set.location.coord[1]; xo[2] = torus_sf.basis_set.location.coord[2]; axis[0] = torus_sf.basis_set.axis.coord[0]; axis[1] = torus_sf.basis_set.axis.coord[1]; axis[2] = torus_sf.basis_set.axis.coord[2]; ref[0] = torus_sf.basis_set.ref_direction.coord[0]; ref[1] = torus_sf.basis_set.ref_direction.coord[1]; ref[2] = torus_sf.basis_set.ref_direction.coord[2]; cr = torus_sf.minor_radius; cc = torus_sf.major_radius; vis_SurfMeshSetConic (surfmesh,conicid, SURFMESH_CONIC_TORUS,sense,xo,axis,ref,cr,cc); #ifdef MESH_DEBUG printf("xo= %e %e %e\n",xo[0],xo[1],xo[2]); printf("axis= %e %e %e\n",axis[0],axis[1],axis[2]); printf("ref= %e %e %e\n",ref[0],ref[1],ref[2]); printf("minor_radius= %e\n",torus_sf.minor_radius); printf("major_radius= %e\n",torus_sf.major_radius); #endif } } /* map fin->edge information */ numnp = numel = 0; finedgeih = vsy_IntHashBegin (); for(ii = 0; ii < fin_edge->length; ii++) { vsy_IntHashInsert (finedgeih,fin_edge->data[ii].fin, fin_edge->data[ii].edge); } /* map point->vertex information */ pointvertexih = vsy_IntHashBegin (); for(ii = 0; ii < point_topol->length; ii++) { vsy_IntHashInsert (pointvertexih,point_topol->data[ii].point+1, point_topol->data[ii].topol); } nodeih = vsy_IntHashBegin (); /* loop over all fins */ length = facet_fin->length; j = 0; for(ii = 0; ii < length; ii++) { finID = facet_fin->data[ii].fin; finIndex = fin_data->data[finID]; point = data_point_idx->point[finIndex]; xl = point_vec->vec[point].coord; vertex[j][0] = xl[0]; vertex[j][1] = xl[1]; vertex[j][2] = xl[2]; normalIndex = data_normal_idx->normal[finIndex]; xn = normal_vec->vec[normalIndex].coord; facetID = facet_fin->data[ii].facet; geoface = facet_face->face[facetID]; PK_FACE_ask_surf (geoface,&surf); vsy_IntHashLookup (conicih,surf,&conicid); vsy_IntHashLookup (finedgeih,finID,&geoedge[(j+2)%3]); vsy_IntHashLookup (nodeih,point+1,&index); /* check for new node */ if(index == 0) { index = ++numnp; /* update extent */ if(index == 1) { minext[0] = maxext[0] = vertex[j][0]; minext[1] = maxext[1] = vertex[j][1]; minext[2] = maxext[2] = vertex[j][2]; } else { if(vertex[j][0] < minext[0]) minext[0] = vertex[j][0]; if(vertex[j][1] < minext[1]) minext[1] = vertex[j][1]; if(vertex[j][2] < minext[2]) minext[2] = vertex[j][2]; if(vertex[j][0] > maxext[0]) maxext[0] = vertex[j][0]; if(vertex[j][1] > maxext[1]) maxext[1] = vertex[j][1]; if(vertex[j][2] > maxext[2]) maxext[2] = vertex[j][2]; } vsy_IntHashInsert (nodeih,point+1,index); /* * Check whether node is on edge/vertex, or interior * to a surface. */ vsy_IntHashLookup (pointvertexih,point+1,&geovert[j]); vsy_IntHashLookup (vertexih,geovert[j],&geobody); if(geobody) { vis_SurfMeshSetPoint (surfmesh,index,vertex[j],1); vis_SurfMeshSetPointAssoc(surfmesh,VIS_GEOVERT,index, geovert[j]); } else { vis_SurfMeshSetPoint (surfmesh,index,vertex[j],0); } } normals[j][0] = xn[0]; normals[j][1] = xn[1]; normals[j][2] = xn[2]; ix[j] = index; ++j; /* every 3 fins => completed triangle */ if(j == 3) { ++numel; /* gather edge information */ for(m = 1; m <= 3; m++) { eflags[m-1] = 0; if(geoedge[m-1]) { eflags[m-1] = 1; } } /* insert triangle, its associations, and normals */ vis_SurfMeshSetTri (surfmesh,numel,ix,eflags); vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,numel,SYS_FACE, 0,geoface); vsy_IntHashLookup (bodylih,geoface,&geobodyrb); vsy_IntHashLookup (bodyrih,geoface,&geobodylb); vis_SurfMeshSetTriBack (surfmesh,numel,geobodyrb,geobodylb); if(geobodyrb) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,numel, SYS_ELEM,0,geobodyrb); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,numel, SYS_ELEM,0,geobodyrb); } if(geobodylb) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,numel, SYS_ELEM,-1,geobodylb); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,numel, SYS_ELEM,-1,geobodylb); } vis_SurfMeshSetTriNorm (surfmesh,numel,normals); if(conicid) { vis_SurfMeshSetTriConic (surfmesh,numel,conicid); } /* compute edge tangents for geometry edges */ for(m = 1; m <= 3; m++) { if(geoedge[m-1]) { /* assign edge association */ vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,numel, SYS_EDGE,m,geoedge[m-1]); /* compute parameter "t" on curve */ etang[0] = vertex[m%3][0] - vertex[m-1][0]; etang[1] = vertex[m%3][1] - vertex[m-1][1]; etang[2] = vertex[m%3][2] - vertex[m-1][2]; PK_EDGE_ask_curve (geoedge[m-1],&curve); /* first point on edge */ pt.coord[0] = vertex[m-1][0]; pt.coord[1] = vertex[m-1][1]; pt.coord[2] = vertex[m-1][2]; err = PK_CURVE_parameterise_vector (curve,pt,&t); /* * An error indicates that the point, although * supposedly on the edge, was placed away from the * during the tesselation. We then try to find * a point on the edge that is as close as possible * to the tesselation point */ if(err != 0) { err = PK_GEOM_range_vector (curve,pt,&options, &range_result,&range); if(err) { printf( "Unable to project point to curve, err= %d\n", err); continue; } t = range.end.parameters[0]; } PK_CURVE_eval_with_tangent (curve,t,0,&pt,&tg); /* make sure tangent is aligned with edge direction */ tang[0][0] = tg.coord[0]; tang[0][1] = tg.coord[1]; tang[0][2] = tg.coord[2]; if(tang[0][0]*etang[0]+tang[0][1]*etang[1]+ tang[0][2]*etang[2] < 0.) { tang[0][0] = -tang[0][0]; tang[0][1] = -tang[0][1]; tang[0][2] = -tang[0][2]; } /* likewise, second point on edge */ pt.coord[0] = vertex[m%3][0]; pt.coord[1] = vertex[m%3][1]; pt.coord[2] = vertex[m%3][2]; err = PK_CURVE_parameterise_vector (curve,pt,&t); if(err != 0) { err = PK_GEOM_range_vector (curve,pt,&options, &range_result,&range); if(err) { printf( "Unable to project point to curve, err= %d\n", err); continue; } t = range.end.parameters[0]; } PK_CURVE_eval_with_tangent (curve,t,0,&pt,&tg); tang[1][0] = tg.coord[0]; tang[1][1] = tg.coord[1]; tang[1][2] = tg.coord[2]; if(tang[1][0]*etang[0]+tang[1][1]*etang[1]+ tang[1][2]*etang[2] < 0.) { tang[1][0] = -tang[1][0]; tang[1][1] = -tang[1][1]; tang[1][2] = -tang[1][2]; } /* set tangents */ vis_SurfMeshSetTriTang (surfmesh,numel,m,tang); } } j = 0; } } vsy_IntHashEnd (nodeih); vsy_IntHashEnd (finedgeih); vsy_IntHashEnd (conicih); vsy_IntHashEnd (pointvertexih); vsy_IntVecEnd (faceorientiv); /* compute extent diagonal lenth for edge length */ diaglen = sqrt( (maxext[0]-minext[0])*(maxext[0]-minext[0]) + (maxext[1]-minext[1])*(maxext[1]-minext[1]) + (maxext[2]-minext[2])*(maxext[2]-minext[2]) ); edgelen = diaglen/20.; vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelen); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,45.); /* generate parabolic triangles */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); /* save SurfMesh file */ if(writesurfmesh) { sprintf(buffer,"exam52pk_%d.srf",parts[i]); vis_SurfMeshWrite (surfmesh,SYS_ASCII,buffer); } /* generate surface mesh and write result */ connectsrf = vis_ConnectBegin (); vis_ConnectPre (connectsrf,SYS_DOUBLE); vis_SurfMeshGenerate (surfmesh,connectsrf); ierr = vis_SurfMeshError (surfmesh); if(ierr) { printf("Error generating surface mesh, part= %d\n",parts[i]); sprintf(filnam,"model-%d.srf",parts[i]); vis_SurfMeshWrite (surfmesh,SYS_ASCII,filnam); vis_ConnectEnd (connectsrf); continue; } printf("SurfMesh part= %d complete\n",parts[i]); vis_ConnectNumber (connectsrf,SYS_NODE,&numnp); vis_ConnectNumber (connectsrf,SYS_ELEM,&numel); printf("Surface number of nodes= %d\n",numnp); printf("Surface number of elems= %d\n",numel); tetmeshoption = 1; /* test for no free edges */ vis_SurfMeshGetInteger (surfmesh,SURFMESH_NUMFREEEDGE,&nfree); if(nfree) { tetmeshoption = 0; } if(tetmeshoption) { connecttet = vis_ConnectBegin (); vis_ConnectPre (connecttet,SYS_DOUBLE); vis_TetMeshConnect (tetmesh,connectsrf); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,edgelen); vis_TetMeshSetParamd (tetmesh,VIS_MESH_GROWTHRATE,2.); /* optional write of TetMesh contents for QA vis_TetMeshWrite (tetmesh,SYS_BINARY,"model1.btet"); */ vis_TetMeshGenerate (tetmesh,connecttet); ierr = vis_TetMeshError (tetmesh); if(ierr) { printf("Error generating tet mesh, part= %d\n",parts[i]); sprintf(filnam,"part_%d.btet",parts[i]); vis_TetMeshWrite (tetmesh,SYS_BINARY,filnam); vis_ConnectEnd (connecttet); vsy_IntHashEnd (bodylih); vsy_IntHashEnd (bodyrih); continue; } printf("TetMesh part= %d complete\n",parts[i]); vis_ConnectAppend (connect,connecttet); vis_ConnectEnd (connecttet); } else { vis_ConnectAppend (connect,connectsrf); } vis_ConnectEnd (connectsrf); } vsy_IntHashEnd (bodylih); vsy_IntHashEnd (bodyrih); } } /* report total number of generate nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("total number of nodes= %d\n",numnp); printf("total number of elems= %d\n",numel); /* optional write of final mesh */ if(numnp && numel) { vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"model.bdf"); } vis_SurfMeshEnd (surfmesh); vis_TetMeshEnd (tetmesh); vsy_IntHashEnd (vertexih); vis_ConnectEnd (connect); PK_MEMORY_free (parts); /* stop Parasolid engine */ parasolid_Term(); }
#include "base/base.h" #include "vis/vismesh.h" #include "vis/visshar.h" #include "base/system.h" #include "vis/exam/exam52occ.hxx" #include <new> #include <stdio.h> static Vdouble rstol[3][2] = { //{1.e-1,1.e-1}, {0.9,1.e-1}, {1.e-1,0.9} }; {ONETHIRD,ONETHIRD},{ONETHIRD,ONETHIRD},{ONETHIRD,ONETHIRD}}; static Vdouble rschord[3][2] = { {0.5,0.5},{0.,0.5},{0.5,0.} }; static Vdouble rsorig[3][2] = { {0.,0.},{1.,0.},{0.,1.} }; /*---------------------------------------------------------------------- Illustrate OpenCASCADE Interface SurfMesh ----------------------------------------------------------------------*/ static void exam52occ_nodeid(vsy_ADTree *adtree, vis_Connect *connect, Vdouble coord[3], Vint isvert, Vint *nvert, Vint *id) { Vint key, numnp, minkey; Vdouble dist, mindist, x[3]; /* see if point already exists */ vsy_ADTreeRefPointInit (adtree,coord); minkey = 0; while (vsy_ADTreeRefPointNext (adtree,&key), key) { vis_ConnectCoordsdv (connect,1,&key,&x); x[0] -= coord[0]; x[1] -= coord[1]; x[2] -= coord[2]; dist = x[0]*x[0] + x[1]*x[1] + x[2]*x[2]; if(minkey == 0) { mindist = dist; minkey = key; } else { if(dist < mindist) { mindist = dist; minkey = key; } } } if(minkey > 0) { *id = minkey; return; } /* add point */ vis_ConnectNumber (connect,SYS_NODE,&numnp); ++numnp; vis_ConnectSetCoordsdv (connect,numnp,coord); if(isvert) { vis_ConnectSetNodeAssoc (connect,VIS_GEOVERT,numnp,++(*nvert)); } vsy_ADTreeInsertPoint (adtree,numnp,coord); *id = numnp; } static void exam52_surfnormal(Handle(Geom_Surface) geomsurf, Standard_Real u, Standard_Real v, Vdouble enorm[3], Vint *flag) { Vint iter; *flag = 0; for(iter = 0; iter < 5; ++iter) { try { GeomLProp_SLProps aProp (geomsurf,u,v,1,Precision::Angular()); gp_Dir normal = aProp.Normal(); normal.Coord(enorm[0],enorm[1],enorm[2]); *flag = 1; return; } catch(Standard_Failure) { u += 1.e-6; v += 1.e-6; } } } static void exam52_edgetang(Handle(Geom_Curve) geomcurve, Standard_Real uv, Vdouble tang[3], Vint *flag) { Vint iter; *flag = 0; for(iter = 0; iter < 5; ++iter) { try { GeomLProp_CLProps aProp (geomcurve,uv,1,Precision::Angular()); gp_Dir tangent; aProp.Tangent(tangent); tangent.Coord(tang[0],tang[1],tang[2]); *flag = 1; return; } catch(Standard_Failure) { uv += 1.e-6; } } } static void exam52occ_configADTree(TopoDS_Shape& myShape, vsy_ADTree *adtree, Vdouble *diaglength) { Vdouble dx, dy, dz, tol; Standard_Real xmin[3], xmax[3]; /* Get bounding box for shape */ Bnd_Box B; BRepBndLib::Add(myShape,B); B.Get (xmin[0],xmin[1],xmin[2],xmax[0],xmax[1],xmax[2]); /* Create ADTree with this bounding box */ dx = xmax[0]-xmin[0]; dy = xmax[1]-xmin[1]; dz = xmax[2]-xmin[2]; /* Set diagonal length of extent box */ *diaglength = sqrt(dx*dx+dy*dy+dz*dz); xmin[0] -= 0.05*dx; xmax[0] += 0.05*dx; xmin[1] -= 0.05*dy; xmax[1] += 0.05*dy; xmin[2] -= 0.05*dz; xmax[2] += 0.05*dz; vsy_ADTreeDef (adtree,ADTREE_POINT,100,xmin,xmax); tol = 1.1*sqrt(dx*dx+dy*dy+dz*dz)*1.e-8; vsy_ADTreeSetParamd (adtree,ADTREE_TOLERANCE,tol); } static void exam52occ_addVertex(TopoDS_Shape& myShape, vsy_ADTree *adtree, vis_Connect *connect, Vint *nvert) { Standard_Real x, y, z; TopExp_Explorer ex; Vdouble coord[3]; Vint id; /* insert all vertices; check for repeated */ for(ex.Init (myShape,TopAbs_VERTEX); ex.More(); ex.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(ex.Current()); gp_Pnt p = BRep_Tool::Pnt(vertex); p.Coord(x,y,z); coord[0] = x; coord[1] = y; coord[2] = z; /* get node id */ exam52occ_nodeid (adtree,connect,coord,1,nvert,&id); } } static void exam52occ_sort3(Vint ix[3]) { Vint imin, imax, kx[3], i; imin = (ix[0] < ix[1]) ? ((ix[0] < ix[2] ? ix[0] : ix[2])) : ((ix[1] < ix[2] ? ix[1] : ix[2])); imax = (ix[0] < ix[1]) ? ((ix[1] < ix[2] ? ix[2] : ix[1])) : ((ix[0] < ix[2] ? ix[2] : ix[0])); kx[0] = kx[1] = kx[2] = 0; for(i = 0; i < 3; ++i) { if(imin == ix[i]) { kx[i] = 1; } if(imax == ix[i]) { kx[i] = 1; } } for(i = 0; i < 3; ++i) { if(kx[i] == 0) { ix[1] = ix[i]; break; } } ix[0] = imin; ix[2] = imax; } int main(int argc, char *argv[]) { TopoDS_Shape myShape; vis_Connect *connect; Vint n, j, k, rev; Vint numnp, numel, nix, ix[3], index, ntri, npts, ixn[3]; Vdouble coord[3]; Vchar brepname[SYS_MAXPATHCHAR]; Vchar srfname[SYS_MAXPATHCHAR]; Vint nvert = 0; Standard_Real x, y, z; vsy_ADTree *adtree; BRep_Builder b; Vint shape, maxi, maxj, maxk, key; Vdouble xyz[3], enorm[3][3]; vsy_IntVHash *ivhenum; vsy_IntHash *ihnode, *ihedge; vsy_VHashTable *vhtang; Vint numedge, numface, in0, in1; Vdouble edgelength = 0.; Vdouble diaglength, chordheight; Vint iquad = 0, itet = 0; Vint ierr; vis_SurfMesh *surfmesh; vis_Connect *connectsrf; vis_TetMesh *tetmesh; vis_Connect *connecttet; vsy_IntVHash *ivhall; /* gather all parameters */ strcpy(srfname,"exam52occ.srf"); for(int iarg = 1; iarg < argc; ++iarg) { if(strcmp(argv[iarg],"-quad")==0) { iquad = 1; } else if(strcmp(argv[iarg],"-srfname")==0) { ++iarg; strcpy(srfname,argv[iarg]); } else if(strcmp(argv[iarg],"-tet")==0) { itet = 1; } else if(strcmp(argv[iarg],"-el")==0) { ++iarg; sscanf(argv[iarg],"%le",&edgelength); } } strcpy(brepname,argv[argc-1]); /* read brep file */ printf("reading file= %s\n",brepname); BRepTools::Read (myShape,brepname,b); if (myShape.IsNull()) { printf("Unable to read brep file= %s\n",brepname); return 1; } /* create Connect object to store geometry tesselation information */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); numnp = numel = nvert = 0; /* create shape with missing additional edges */ TopoDS_Compound toadd; ihedge = vsy_IntHashBegin (); ivhenum = vsy_IntVHashBegin (); vhtang = vsy_VHashTableBegin (); vsy_IntVHashDef (ivhenum,2,100); vsy_VHashTableDef (vhtang,2,100); /* create ADTree to generate unique points */ adtree = vsy_ADTreeBegin (); exam52occ_configADTree (myShape,adtree,&diaglength); /* set meshing edgelength, tesselation chordheight */ if(edgelength == 0.) { edgelength = .05*diaglength; } chordheight = .001*diaglength; /* tesseleate geometry */ BRepTools::Clean (myShape); BRepMesh_IncrementalMesh (myShape,chordheight); /* insert all vertices; check for repeated */ exam52occ_addVertex (myShape,adtree,connect,&nvert); /* extract face tesselation */ TopTools_IndexedMapOfShape faceMap; TopExp::MapShapes(myShape, TopAbs_FACE, faceMap); ivhall = vsy_IntVHashBegin (); vsy_IntVHashDef (ivhall,3,faceMap.Extent()); numedge = 0; numface = 0; for(int j = 1; j <= faceMap.Extent(); ++j) { const TopoDS_Face& face = TopoDS::Face(faceMap(j)); numface += 1; /* Extract geometric surface from face */ TopLoc_Location surflocation; Handle(Geom_Surface) geomsurf = BRep_Tool::Surface(face,surflocation); /* Map nodes on this face */ vsy_IntVHash *ivhfreeedges; ivhfreeedges = vsy_IntVHashBegin (); vsy_IntVHashDef (ivhfreeedges,2,100); TopLoc_Location location; Handle_Poly_Triangulation triangulation = BRep_Tool::Triangulation (face, location); if(triangulation.IsNull()) continue; const TColgp_Array1OfPnt& nodes = triangulation->Nodes (); const Poly_Array1OfTriangle& triangles = triangulation->Triangles (); const TColgp_Array1OfPnt2d& uvnodes = triangulation->UVNodes (); /* store all nodes first */ Vint minnode = nodes.Lower(); Vint maxnode = nodes.Upper(); Vint sizenode = maxnode - minnode + 1; Vint *nodemap = (Vint*)malloc(sizenode*sizeof(Vint)); for(int i = minnode; i <= maxnode; i++) { const gp_Pnt& p1 = nodes (i); p1.Coord(x,y,z); location.Transformation().Transforms(x,y,z); coord[0] = x; coord[1] = y; coord[2] = z; exam52occ_nodeid (adtree,connect,coord,0,&nvert,&index); nodemap[i-minnode] = index; } /* Iterate over the triangles and their nodes */ Vint firstflagged = 0; for (int i = triangles.Lower (); i <= triangles.Upper(); ++i) { const Poly_Triangle& triangle = triangles (i); triangle.Get(ixn[0],ixn[1],ixn[2]); /* first loop through nodes */ for(k = 0; k < 3; k++) { ix[k] = nodemap[ixn[k]-minnode]; } ++numel; /* check for degenerate triangle */ if(ix[0] == ix[1] || ix[0] == ix[2] || ix[1] == ix[2]) { vis_ConnectSetTopology (connect,numel,SYS_SHAPEPOINT,1,0,0); vis_ConnectSetElemNode (connect,numel,ix); continue; } vis_ConnectSetTopology (connect,numel,SYS_SHAPETRI,0,0,0); vis_ConnectSetElemNode (connect,numel,ix); vis_ConnectSetElemAssoc (connect,VIS_GEOFACE,numel,j); if(face.Orientation() == TopAbs_REVERSED) { vis_ConnectSetElemAssoc (connect,VIS_MISCID,numel,1); } /* second loop through nodes for normals */ Vint flag, normflag = 0; Standard_Real uvo[3][2], uvtol[3][2]; for(k = 0; k < 3; k++) { const gp_Pnt2d& uv = uvnodes (triangle (k+1)); uv.Coord(uvo[k][0],uvo[k][1]); } /* check for geovert */ Vint vertid[3]; vis_ConnectNodeAssoc (connect,VIS_GEOVERT,3,ix,vertid); #ifdef OLDWAY Vdouble h[3]; for(k = 0; k < 3; k++) { if(vertid[k]) { vis_shape2DGendv (1,SYS_SHAPETRI,0,0,rstol[k],h,NULL); uvtol[k][0] = h[0]*uvo[0][0]+h[1]*uvo[1][0]+h[2]*uvo[2][0]; uvtol[k][1] = h[0]*uvo[0][1]+h[1]*uvo[1][1]+h[2]*uvo[2][1]; } else { MOVE2(uvo[k],uvtol[k]); } } #endif Vdouble enormal[3], xtri[3][3], v1[3], v2[3]; vis_ConnectCoordsdv (connect,3,ix,xtri); DIFF3(xtri[1],xtri[0],v1); DIFF3(xtri[2],xtri[0],v2); CROSS3(v1,v2,enormal); UNIT3(enormal); for(k = 0; k < 3; k++) { const gp_Pnt2d& uv = uvnodes (triangle (k+1)); if(vertid[k]) { Vdouble uvv[2], h[3]; for(int l = 0; l < 10; ++l) { uvv[0] = rsorig[k][0] + (rschord[k][0]-rsorig[k][0])*0.1*l; uvv[1] = rsorig[k][0] + (rschord[k][0]-rsorig[k][0])*0.1*l; vis_shape2DGendv (1,SYS_SHAPETRI,0,0,uvv,h,NULL); uvtol[k][0] = h[0]*uvo[0][0]+h[1]*uvo[1][0]+h[2]*uvo[2][0]; uvtol[k][1] = h[0]*uvo[0][1]+h[1]*uvo[1][1]+h[2]*uvo[2][1]; exam52_surfnormal (geomsurf,uvtol[k][0],uvtol[k][1], enorm[k],&flag); if(flag == 1) { ++normflag; gp_Vec vec = gp_Vec(enorm[k][0],enorm[k][1],enorm[k][2]); gp_Vec nvec = surflocation.Transformation().GetRotation().Multiply(vec); nvec.Coord(enorm[k][0],enorm[k][1],enorm[k][2]); } if(DOT3(enorm[k],enormal) > 0.8) break; } } else { exam52_surfnormal (geomsurf,uvo[k][0],uvo[k][1],enorm[k],&flag); if(flag == 1) { ++normflag; gp_Vec vec = gp_Vec(enorm[k][0],enorm[k][1],enorm[k][2]); gp_Vec nvec = surflocation.Transformation().GetRotation().Multiply(vec); nvec.Coord(enorm[k][0],enorm[k][1],enorm[k][2]); } } } vis_ConnectSetElemNormdv (connect,numel,1,enorm); /* mark edges */ Vint jx[2], key; for(k = 0; k < 3; k++) { jx[0] = ix[k] > ix[(k+1)%3] ? ix[(k+1)%3] : ix[k]; jx[1] = ix[k] > ix[(k+1)%3] ? ix[k] : ix[(k+1)%3]; vsy_IntVHashLookup (ivhfreeedges,jx,&key); ++key; vsy_IntVHashInsert (ivhfreeedges,jx,key); } /* sort nodes min to max and store unique connectivity */ if(firstflagged == 0) { exam52occ_sort3 (ix); vsy_IntVHashInsert (ivhall,ix,numel); firstflagged = 1; } } Vint en = 1; TopExp_Explorer ExpW; for (ExpW.Init (face,TopAbs_EDGE); ExpW.More(); ExpW.Next()) { ++en; TopoDS_Shape shapw = ExpW.Current(); TopoDS_Edge edge = TopoDS::Edge(shapw); TopLoc_Location edgelocation; Standard_Real cfirst, clast; Handle(Geom_Curve) geomcurve = BRep_Tool::Curve(edge,edgelocation,cfirst,clast); if(geomcurve.IsNull()) continue; TopLoc_Location tlocation; Handle(Poly_PolygonOnTriangulation) edgeMesh; edgeMesh = BRep_Tool::PolygonOnTriangulation(edge,triangulation,tlocation); if(edgeMesh.IsNull()) continue; Handle(TColStd_HArray1OfReal) unodes = edgeMesh->Parameters (); const TColStd_Array1OfInteger& enodes = edgeMesh->Nodes (); Vint *indices = (Vint*)malloc(edgeMesh->NbNodes()*sizeof(Vint)); Vdouble *tang = (Vdouble*)malloc(3*edgeMesh->NbNodes()*sizeof(Vdouble)); Vint flag; for(k = 1; k <= edgeMesh->NbNodes(); ++k) { indices[k-1] = nodemap[enodes(k)-1]; /* get tangent */ const Standard_Real u = unodes->Value(k); exam52_edgetang (geomcurve,u,tang+3*(k-1),&flag); if(flag == 1) { gp_Vec vec = gp_Vec(tang[3*(k-1)],tang[3*(k-1)+1], tang[3*(k-1)+2]); gp_Vec nvec = edgelocation.Transformation().GetRotation().Multiply(vec); nvec.Coord(tang[3*(k-1)],tang[3*(k-1)+1],tang[3*(k-1)+2]); } else { tang[3*(k-1)] = 2.; } } for(k = 1; k <= edgeMesh->NbNodes()-1; ++k) { Vdouble *atang; Vint jx[2]; ix[0] = indices[k-1]; ix[1] = indices[k]; /* update free edges */ jx[0] = ix[0] > ix[1] ? ix[1] : ix[0]; jx[1] = ix[0] > ix[1] ? ix[0] : ix[1]; vsy_IntVHashInsert (ivhfreeedges,jx,-1); if(k == 1) { vsy_IntVHashLookup (ivhenum,ix,&key); if(key == 0 || key == -1) { key = ++numedge; } } vsy_IntVHashLookup (ivhenum,ix,&n); if(n <= 0) { /* check reversed edge */ vsy_IntVHashLookup (ivhenum,jx,&n); if(n <= 0) { if(tang[3*(k-1)] != 2. && tang[3*k] != 2.) { vsy_IntVHashInsert (ivhenum,ix,key); atang = (Vdouble*)malloc(6*sizeof(Vdouble)); vut_CopyD (tang+3*(k-1),atang,6); vsy_VHashTableInsert (vhtang,ix,atang); } } } } free (indices); free (tang); } free (nodemap); /* add remaining free edges */ vsy_IntVHashInitIter (ivhfreeedges); while(vsy_IntVHashNextIter (ivhfreeedges,ix,&key), key) { if(key == 1) { vsy_IntVHashLookup (ivhenum,ix,&k); if(k == 0) { Vint nx[2]; nx[0] = ix[1]; nx[1] = ix[0]; vsy_IntVHashLookup (ivhenum,nx,&k); if(k == 0) { vsy_IntVHashInsert (ivhenum,ix,-1); } } } } vsy_IntVHashEnd (ivhfreeedges); } /* determine double-backed surfaces */ Vint *ibody = (Vint*)malloc(2*numel*sizeof(Vint)); vut_ZeroI (ibody,2*numel); Vint nbody = 0; TopExp_Explorer ExpS; for (ExpS.Init (myShape,TopAbs_SOLID); ExpS.More(); ExpS.Next()) { TopoDS_Shape shapw = ExpS.Current(); TopoDS_Solid solid = TopoDS::Solid(shapw); ++nbody; TopExp_Explorer ExpF; for (ExpF.Init (solid,TopAbs_FACE); ExpF.More(); ExpF.Next()) { TopoDS_Shape shapz = ExpF.Current(); TopoDS_Face face = TopoDS::Face(shapz); TopLoc_Location location; Handle_Poly_Triangulation triangulation = BRep_Tool::Triangulation (face, location); if(triangulation.IsNull()) continue; const TColgp_Array1OfPnt& nodes = triangulation->Nodes (); const Poly_Array1OfTriangle& triangles = triangulation->Triangles (); /* Iterate over the triangles and their nodes */ Vint firstflagged = 0; for (int i = triangles.Lower (); i <= triangles.Upper(); ++i) { const Poly_Triangle& triangle = triangles (i); if(firstflagged == 0) { /* extract first element index */ for(k = 0; k < 3; k++) { const gp_Pnt& p1 = nodes (triangle (k+1)); p1.Coord(x,y,z); location.Transformation().Transforms(x,y,z); coord[0] = x; coord[1] = y; coord[2] = z; exam52occ_nodeid (adtree,connect,coord,0,&nvert,&ix[k]); } if(ix[0] == ix[1] || ix[0] == ix[2] || ix[1] == ix[2]) { continue; } firstflagged = 1; exam52occ_sort3 (ix); vsy_IntVHashLookup (ivhall,ix,&key); } else { /* increment element index */ ++key; } vis_ConnectElemAssoc (connect,VIS_MISCID,1,&key,&rev); if(face.Orientation() == TopAbs_REVERSED) { if(rev) { ibody[2*(key-1) ] = nbody; } else { ibody[2*(key-1)+1] = nbody; } } else { if(rev) { ibody[2*(key-1)+1] = nbody; } else { ibody[2*(key-1) ] = nbody; } } } } } vsy_IntVHashEnd (ivhall); /* create SurfMesh */ surfmesh = vis_SurfMeshBegin (); vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); ntri = npts = 0; ihnode = vsy_IntHashBegin (); for(n = 1; n <= numel; ++n) { vis_ConnectTopology (connect,n,&shape,&maxi,&maxj,&maxk); if(shape != SYS_SHAPETRI) continue; ++ntri; vis_ConnectElemNode (connect,n,&nix,ix); for(j = 0; j < 3; ++j) { vsy_IntHashLookup (ihnode,ix[j],&key); if(key == 0) { ++npts; vsy_IntHashInsert (ihnode,ix[j],npts); } } } if(npts == 0 || ntri == 0) goto labelcleanup; vis_SurfMeshDef (surfmesh,npts,ntri); /* load points */ for(n = 1; n <= numnp; ++n) { vsy_IntHashLookup (ihnode,n,&j); if(j == 0) continue; vis_ConnectCoordsdv (connect,1,&n,&xyz); vis_ConnectNodeAssoc (connect,VIS_GEOVERT,1,&n,&nvert); if(nvert) { vis_SurfMeshSetPoint (surfmesh,j,xyz,1); vis_SurfMeshSetPointAssoc (surfmesh,VIS_GEOVERT,j,nvert); } else { vis_SurfMeshSetPoint (surfmesh,j,xyz,0); } } /* load triangles */ ntri = 0; static Vint irev[3] = {2,1,0}; for(n = 1; n <= numel; ++n) { Vint tefl[3] = {0,0,0}; Vint teflag = 0; Vint tesens[3] = {0,0,0}; Vint jx[3], aid, enormflag; Vdouble *etang[3] = {NULL, NULL, NULL}; vis_ConnectTopology (connect,n,&shape,&maxi,&maxj,&maxk); if(shape != SYS_SHAPETRI) continue; ++ntri; vis_ConnectElemNode (connect,n,&nix,ix); vis_ConnectElemAssoc (connect,VIS_GEOFACE,1,&n,&aid); vis_ConnectElemAssoc (connect,VIS_MISCID,1,&n,&rev); /* loop over triangle edges */ for(k = 0; k < 3; k++) { if(rev == 0) { in0 = k; in1 = (k+1)%3; } else { in1 = irev[k]; in0 = (irev[k]+1)%3; } jx[0] = ix[in0]; jx[1] = ix[in1]; vsy_IntVHashLookup (ivhenum,jx,&teflag); if(teflag == 0) { jx[0] = ix[in1]; jx[1] = ix[in0]; vsy_IntVHashLookup (ivhenum,jx,&teflag); if(teflag) { tesens[k] = 1; tefl[k] = 1; } } else { tefl[k] = 1; } if(tefl[k]) { if(teflag > 0) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,ntri,SYS_EDGE,k+1, teflag); } vsy_VHashTableLookup (vhtang,jx,(Vobject**)&etang[k]); } } if(rev == 0) { vsy_IntHashLookup (ihnode,ix[0],&jx[0]); vsy_IntHashLookup (ihnode,ix[1],&jx[1]); vsy_IntHashLookup (ihnode,ix[2],&jx[2]); } else { vsy_IntHashLookup (ihnode,ix[0],&jx[0]); vsy_IntHashLookup (ihnode,ix[1],&jx[2]); vsy_IntHashLookup (ihnode,ix[2],&jx[1]); } vis_SurfMeshSetTri (surfmesh,ntri,jx,tefl); if(ibody[2*(n-1) ] > 0 && ibody[2*(n-1)+1] > 0) { vis_SurfMeshSetTriBack (surfmesh,ntri,1,1); vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,ntri,SYS_ELEM, 0,ibody[2*(n-1)]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,ntri,SYS_ELEM, -1,ibody[2*(n-1)+1]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,ntri,SYS_ELEM, 0,ibody[2*(n-1)]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,ntri,SYS_ELEM, -1,ibody[2*(n-1)+1]); } else if(ibody[2*(n-1)] > 0) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOBODY,ntri,SYS_ELEM, 0,ibody[2*(n-1)]); vis_SurfMeshSetTriAssoc (surfmesh,VIS_PROPID,ntri,SYS_ELEM, 0,ibody[2*(n-1)]); } /* set triangle node normals */ vis_ConnectIsElemNorm (connect,n,1,&enormflag); if(enormflag) { vis_ConnectElemNormdv (connect,n,1,enorm); if(rev) { Vdouble tmp[3]; tmp[0] = enorm[1][0]; tmp[1] = enorm[1][1]; tmp[2] = enorm[1][2]; enorm[1][0] = enorm[2][0]; enorm[1][1] = enorm[2][1]; enorm[1][2] = enorm[2][2]; enorm[2][0] = tmp[0]; enorm[2][1] = tmp[1]; enorm[2][2] = tmp[2]; for(k = 0; k < 3; k++) { enorm[0][k] = -enorm[0][k]; enorm[1][k] = -enorm[1][k]; enorm[2][k] = -enorm[2][k]; } } vis_SurfMeshSetTriNorm (surfmesh,ntri,enorm); } vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,ntri,SYS_FACE,0,aid); /* set triangle edge tangents */ for(k = 0; k < 3; k++) { if(tefl[k] == 0 || etang[k] == NULL) continue; if(tesens[k] == 0) { vis_SurfMeshSetTriTang (surfmesh,ntri,k+1,(Vdouble(*)[3])etang[k]); } else { Vdouble copy[6]; for(int i = 0; i < 3; ++i) { copy[i ] = -etang[k][i+3]; copy[i+3] = -etang[k][i ]; } vis_SurfMeshSetTriTang (surfmesh,ntri,k+1,(Vdouble(*)[3])copy); } } } /* end objects */ labelcleanup: free (ibody); vsy_VHashTableForEach (vhtang,(Vfunc1*)free); vsy_VHashTableEnd (vhtang); vsy_IntHashEnd (ihnode); vsy_IntHashEnd (ihedge); vsy_IntVHashEnd (ivhenum); vis_ConnectEnd (connect); vsy_ADTreeEnd (adtree); printf("Geometry read complete\n"); printf(" Number of geometry edges= %d\n", numedge); printf(" Number of geometry faces= %d\n", numface); printf(" Number of geometry bodies= %d\n", nbody); printf(" Number of tesselation points= %d\n", npts); printf(" Number of tesselation tris= %d\n", ntri); if(npts == 0 || ntri == 0) { vis_SurfMeshEnd (surfmesh); return 1; } if(iquad) { vis_SurfMeshSetParami (surfmesh,VIS_MESH_SHAPE,VIS_SHAPEQUAD); } vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelength); printf("edgelength= %e\n",edgelength); vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,1); /* optional write of SurfMesh contents for QA */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,srfname); connectsrf = vis_ConnectBegin(); vis_SurfMeshGenerate (surfmesh,connectsrf); ierr = vis_SurfMeshError (surfmesh); if(ierr) { printf("Error generating surface mesh\n"); } else { Vint numnpsrf, numelsrf; printf("SurfMesh complete\n"); vis_ConnectNumber (connectsrf, SYS_NODE, &numnpsrf); vis_ConnectNumber (connectsrf, SYS_ELEM, &numelsrf); printf(" Surface number of nodes= %d\n", numnpsrf); printf(" Surface number of elems= %d\n", numelsrf); /* optional write of SurfMesh mesh vis_ConnectWrite (connectsrf,SYS_NASTRAN_BULKDATA,"exam52occ-srf.bdf"); */ /* perform tet mesh */ if(nbody) itet = 1; if(itet) { connecttet = vis_ConnectBegin(); tetmesh = vis_TetMeshBegin (); vis_TetMeshConnect (tetmesh,connectsrf); vis_TetMeshSetParamd (tetmesh,VIS_MESH_EDGELENGTH,edgelength); /* optional write of TetMesh contents for QA vis_TetMeshWrite (tetmesh,SYS_ASCII,"exam52occ.tet"); */ vis_TetMeshGenerate (tetmesh,connecttet); if(ierr) { printf("Error generating tet mesh\n"); } else { Vint numnptet, numeltet; printf("TetMesh complete\n"); vis_ConnectNumber (connecttet, SYS_NODE, &numnptet); vis_ConnectNumber (connecttet, SYS_ELEM, &numeltet); printf(" Tet mesh number of nodes= %d\n", numnptet); printf(" Tet mesh number of elems= %d\n", numeltet); /* optional write of TetMesh mesh vis_ConnectWrite (connecttet,SYS_NASTRAN_BULKDATA, "exam52occ-tet.bdf"); */ } vis_ConnectEnd (connecttet); vis_TetMeshEnd (tetmesh); } } vis_SurfMeshEnd (surfmesh); vis_ConnectEnd (connectsrf); return 0; }
The edges around the circular hole are given a special preserved edge flag of 2 which will purge the edge of any points which are not preserved. Note that interior midside nodes of some of the generated triangles connected to the circular hole have been adjusted to avoid local element inversions at or near the edge of the hole.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble xc[21][3] = { { 5.000e-01, 0.000e+00, 0.000e+00}, { 4.330e-01, 2.500e-01, 0.000e+00}, { 2.500e-01, 4.330e-01, 0.000e+00}, { 0.000e+00, 5.000e-01, 0.000e+00}, {-2.500e-01, 4.330e-01, 0.000e+00}, {-4.330e-01, 2.500e-01, 0.000e+00}, {-5.000e-01, 0.000e+00, 0.000e+00}, {-4.330e-01, -2.500e-01, 0.000e+00}, {-2.500e-01, -4.330e-01, 0.000e+00}, { 0.000e+00, -5.000e-01, 0.000e+00}, { 2.500e-01, -4.330e-01, 0.000e+00}, { 4.330e-01, -2.500e-01, 0.000e+00}, { 1., 1., 0.}, {-1., 1., 0.}, {-1., -1., 0.}, { 1., -1., 0.}, { 3.536e-01, 3.536e-01, 0.000e+00}, {-3.536e-01, 3.536e-01, 0.000e+00}, {-3.536e-01, -3.536e-01, 0.000e+00}, { 3.536e-01, -3.536e-01, 0.000e+00}, { 7.500e-01, 0.000e+00, 0.000e+00} }; static Vint pc[21] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; static Vdouble tng[12][3] = { { 0.000, -1.000, 0.000}, { 0.500, -0.866, 0.000}, { 0.866, -0.500, 0.000}, { 1.000, 0.000, 0.000}, { 0.866, 0.500, 0.000}, { 0.500, 0.866, 0.000}, { 0.000, 1.000, 0.000}, {-0.500, 0.866, 0.000}, {-0.866, 0.500, 0.000}, {-1.000, 0.000, 0.000}, {-0.866, -0.500, 0.000}, {-0.500, -0.866, 0.000} }; static Vdouble tvn[3][3] = { {0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.} }; static Vint tix[16][3] = { { 1, 13, 2}, { 2, 13, 3}, { 3, 13, 4}, { 4, 14, 5}, { 5, 14, 6}, { 6, 14, 7}, { 7, 15, 8}, { 8, 15, 9}, { 9, 15, 10}, {10, 16, 11}, {11, 16, 12}, {12, 16, 1}, { 1, 16, 13}, { 4, 13, 14}, { 7, 14, 15}, {10, 15, 16} }; static Vint efl[16][3] = { {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; /*---------------------------------------------------------------------- Generate a 3D Surface Mesh with User Nodes ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_Connect *connect; Vint i, k; Vint numtris, numpnts; Vint numnp, numel; Vdouble x[3]; Vdouble sn[2][3]; Vint aid, pid; Vint nix, ix[6]; Vint i1, i2; Vint numnegjac, qualflag; numpnts = 21; numtris = 16; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < numpnts; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* define triangle connectivity */ for (i = 0; i < numtris; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,tvn); } /* define triangle side tangents for triangle edges in circle */ for (i = 0; i < 12; i++) { i1 = tix[i][2]; i2 = tix[i][0]; for(k = 0; k < 3; k++) { sn[0][k] = tng[i1-1][k]; sn[1][k] = tng[i2-1][k]; } vis_SurfMeshSetTriTang (surfmesh,i+1,3,sn); } /* set unconnected point hints for points 17-20 */ vis_SurfMeshSetTriHint (surfmesh,2,SYS_EDGE,3,17); vis_SurfMeshSetTriHint (surfmesh,5,SYS_EDGE,3,18); vis_SurfMeshSetTriHint (surfmesh,8,SYS_EDGE,3,19); vis_SurfMeshSetTriHint (surfmesh,11,SYS_EDGE,3,20); /* set unconnected point hint for point 21 */ vis_SurfMeshSetTriHint (surfmesh,12,SYS_FACE,0,21); /* set point associations */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,17,1017); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,18,1018); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,19,1019); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,20,1020); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,21,1021); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,60.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.04); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.4); /* generate */ vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam60.srf"); vis_SurfMeshGenerate (surfmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); /* query for negative jacobians */ vis_SurfMeshGetInteger (surfmesh,SURFMESH_NUMNEGJAC,&numnegjac); if(numnegjac) { printf(" Number of negative jacobians= %d\n",numnegjac); for(i = 1; i <= numel; i++) { vis_ConnectElemAssoc (connect,VIS_QUALFLAG,1,&i,&qualflag); if(qualflag != 0) { printf(" element= %d\n",i); } } } /* print node information */ printf("Node information\n"); for(i = 1; i <= numnp; i++) { vis_ConnectCoordsdv (connect,1,&i,(Vdouble(*)[3])x); vis_ConnectNodeAssoc (connect,VIS_MISCID,1,&i,&aid); printf("id= %d x= %f, y= %f, z= %f, aid= %d\n", i,x[0],x[1],x[2],aid); } /* print element information */ printf("Element information\n"); for(i = 1; i <= numel; i++) { vis_ConnectElemNode (connect,i,&nix,ix); vis_ConnectElemAssoc (connect,VIS_PROPID,1,&i,&pid); printf("id= %d ix= %d %d %d %d %d %d, pid= %d\n", i,ix[0],ix[1],ix[2],ix[3],ix[4],ix[5],pid); } /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam60.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_SurfMeshEnd (surfmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble xc[21][3] = { { 5.000e-01, 0.000e+00, 0.000e+00}, { 4.330e-01, 2.500e-01, 0.000e+00}, { 2.500e-01, 4.330e-01, 0.000e+00}, { 0.000e+00, 5.000e-01, 0.000e+00}, {-2.500e-01, 4.330e-01, 0.000e+00}, {-4.330e-01, 2.500e-01, 0.000e+00}, {-5.000e-01, 0.000e+00, 0.000e+00}, {-4.330e-01, -2.500e-01, 0.000e+00}, {-2.500e-01, -4.330e-01, 0.000e+00}, { 0.000e+00, -5.000e-01, 0.000e+00}, { 2.500e-01, -4.330e-01, 0.000e+00}, { 4.330e-01, -2.500e-01, 0.000e+00}, { 1., 1., 0.}, {-1., 1., 0.}, {-1., -1., 0.}, { 1., -1., 0.}, { 3.536e-01, 3.536e-01, 0.000e+00}, {-3.536e-01, 3.536e-01, 0.000e+00}, {-3.536e-01, -3.536e-01, 0.000e+00}, { 3.536e-01, -3.536e-01, 0.000e+00}, { 7.500e-01, 0.000e+00, 0.000e+00} }; static Vint pc[21] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; static Vdouble tng[12][3] = { { 0.000, -1.000, 0.000}, { 0.500, -0.866, 0.000}, { 0.866, -0.500, 0.000}, { 1.000, 0.000, 0.000}, { 0.866, 0.500, 0.000}, { 0.500, 0.866, 0.000}, { 0.000, 1.000, 0.000}, {-0.500, 0.866, 0.000}, {-0.866, 0.500, 0.000}, {-1.000, 0.000, 0.000}, {-0.866, -0.500, 0.000}, {-0.500, -0.866, 0.000} }; static Vdouble tvn[3][3] = { {0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.} }; static Vint tix[16][3] = { { 1, 13, 2}, { 2, 13, 3}, { 3, 13, 4}, { 4, 14, 5}, { 5, 14, 6}, { 6, 14, 7}, { 7, 15, 8}, { 8, 15, 9}, { 9, 15, 10}, {10, 16, 11}, {11, 16, 12}, {12, 16, 1}, { 1, 16, 13}, { 4, 13, 14}, { 7, 14, 15}, {10, 15, 16} }; static Vint efl[16][3] = { {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; /*---------------------------------------------------------------------- Refine a 3D Surface Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_Connect *connect; vis_State *state; Vint i, k; Vint numtris, numpnts; Vint numnp, numel; Vdouble x[3]; Vdouble sn[2][3]; Vdouble v; Vint nix, ix[6]; Vint i1, i2; numpnts = 21; numtris = 16; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,numpnts,numtris); /* create Connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define points */ for (i = 0; i < numpnts; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],pc[i]); } /* define triangle connectivity */ for (i = 0; i < numtris; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tix[i],efl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,tvn); } /* define triangle side tangents for triangle edges in circle */ for (i = 0; i < 12; i++) { i1 = tix[i][2]; i2 = tix[i][0]; for(k = 0; k < 3; k++) { sn[0][k] = tng[i1-1][k]; sn[1][k] = tng[i2-1][k]; } vis_SurfMeshSetTriTang (surfmesh,i+1,3,sn); } /* set unconnected point hints for points 17-20 */ vis_SurfMeshSetTriHint (surfmesh,2,SYS_EDGE,3,17); vis_SurfMeshSetTriHint (surfmesh,5,SYS_EDGE,3,18); vis_SurfMeshSetTriHint (surfmesh,8,SYS_EDGE,3,19); vis_SurfMeshSetTriHint (surfmesh,11,SYS_EDGE,3,20); /* set unconnected point hint for point 21 */ vis_SurfMeshSetTriHint (surfmesh,12,SYS_FACE,0,21); /* set point associations */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,17,1017); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,18,1018); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,19,1019); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,20,1020); vis_SurfMeshSetPointAssoc (surfmesh,VIS_MISCID,21,1021); /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,3); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_SPANANGLE,45.); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_MINEDGELENGTH,.04); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,.3); vis_SurfMeshSetParami (surfmesh,VIS_MESH_SHAPE,SYS_SHAPEQUAD); /* generate */ vis_SurfMeshGenerate (surfmesh,connect); vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Original mesh complete\n"); printf("numnp= %d, numel= %d\n",numnp,numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam60a-orig.bdf"); state = vis_StateBegin (); vis_StateDef (state,numel,SYS_ELEM,SYS_NONE,VIS_SCALAR); /* refine elements in upper right corner */ for(i = 1; i <= numel; ++i) { vis_ConnectElemNode (connect,i,&nix,ix); vis_ConnectCoordsdv (connect,1,&ix[0],(Vdouble(*)[3])x); if(x[0] >= .6 && x[1] >= .6) { v = .1; vis_StateSetDatadv (state,i,&v); } } /* clear Connect object */ vis_ConnectDef (connect,0,0); vis_SurfMeshRefine (surfmesh,state,connect); vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("Refined mesh complete\n"); printf("numnp= %d, numel= %d\n",numnp,numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam60a-ref.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_StateEnd (state); vis_SurfMeshEnd (surfmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint tris[16][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,2,4}, {5,4,7}, {5,4,2}, {5,7,4} }; /* fill regions */ static Vint rtris[16] = { 1,1,2,2, 1,2,1,2, 1,1,2,2, 1,1,2,2 }; /*---------------------------------------------------------------------- Generate a 3D Volume Mesh ----------------------------------------------------------------------*/ int main() { vis_VolMesh *volmesh; vis_Connect *connect; Vint i; Vint numnp, numel; /* create volmesh object */ volmesh = vis_VolMeshBegin (); vis_VolMeshDef (volmesh,8,16); /* create connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < 8; i++) { vis_VolMeshSetNode (volmesh,i+1,coords[i]); } /* define tris */ for (i = 0; i < 16; i++) { vis_VolMeshSetFace (volmesh,i+1,VIS_SHAPETRI,2,0,tris[i]); /* define region fill types */ if(rtris[i] == 1) { vis_VolMeshSetFaceFill (volmesh,i+1,VOLMESH_FILL_TET); } else if(rtris[i] == 2) { vis_VolMeshSetFaceFill (volmesh,i+1,VOLMESH_FILL_BOUNDARY); } } /* define a node association on node 2 */ vis_VolMeshSetNodeAssoc (volmesh,VIS_GEOVERT,2,1000); /* define an element edge association on tri 4, edge 2 */ vis_VolMeshSetFaceAssoc (volmesh,VIS_GEOEDGE,4,SYS_EDGE,2,10); /* define an element face association on tri 3 */ vis_VolMeshSetFaceAssoc (volmesh,VIS_GEOFACE,3,SYS_FACE,1,100); /* define an element association on tri 3 */ vis_VolMeshSetFaceAssoc (volmesh,VIS_GEOBODY,3,SYS_ELEM,0,200); /* generate */ vis_VolMeshGenerate (volmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam61.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_VolMeshEnd (volmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[8][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.} }; static Vint faces[15][4] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,3,4,2}, {5,8,7}, {5,6,8}, {5,2,4}, {5,4,7}, {5,4,2}, {5,7,4} }; static Vint shapefaces[15] = { SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPEQUAD, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI }; static Vint rfaces[15] = { 1,1,2,2, 1,2,1,2, 1,2,2, 1,1,2,2 }; /*---------------------------------------------------------------------- monitor function ----------------------------------------------------------------------*/ static void monitor(vis_VolMesh *volmesh, Vobject *usrobj) { int iparam[4]; printf("monitor called\n"); /* query and print progress */ vis_VolMeshGetInteger (volmesh,VIS_MESH_PROGRESS,iparam); printf("phase= %d\n",iparam[0]); printf("numnp= %d\n",iparam[1]); printf("numel= %d\n",iparam[2]); printf("percent= %d\n",iparam[3]); } /*---------------------------------------------------------------------- Generate a Mixed Shape 3D Volume Mesh ----------------------------------------------------------------------*/ int main() { vis_VolMesh *volmesh; vis_Connect *connect; Vint i; Vint numnp, numel; /* create volmesh object */ volmesh = vis_VolMeshBegin (); vis_VolMeshDef (volmesh,8,15); /* create connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < 8; i++) { vis_VolMeshSetNode (volmesh,i+1,coords[i]); } /* define faces */ for (i = 0; i < 15; i++) { vis_VolMeshSetFace (volmesh,i+1,shapefaces[i],2,0,faces[i]); if(rfaces[i] == 1) { vis_VolMeshSetFaceFill (volmesh,i+1,VOLMESH_FILL_TET); } else if(rfaces[i] == 2) { vis_VolMeshSetFaceFill (volmesh,i+1,VOLMESH_FILL_BOUNDARY); } } /* define a node association on node 2 */ vis_VolMeshSetNodeAssoc (volmesh,VIS_GEOVERT,2,1000); /* define an element edge association on tri 4, edge 2 */ vis_VolMeshSetFaceAssoc (volmesh,VIS_GEOEDGE,4,SYS_EDGE,2,10); /* define an element face association on tri 3 */ vis_VolMeshSetFaceAssoc (volmesh,VIS_GEOFACE,3,SYS_FACE,1,100); /* define an element association on tri 3 */ vis_VolMeshSetFaceAssoc (volmesh,VIS_GEOBODY,3,SYS_ELEM,0,200); vis_VolMeshSetFaceAssoc (volmesh,VIS_PROPID,3,SYS_ELEM,0,1); vis_VolMeshWrite (volmesh,SYS_ASCII,"exam61a.vol"); /* set monitor function */ vis_VolMeshSetFunction (volmesh,VOLMESH_FUN_MONITOR,(Vfunc*)monitor,NULL); /* generate */ vis_VolMeshGenerate (volmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam61a.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_VolMeshEnd (volmesh); return 0; }
The macro MAXJ_SETMISSINGMIDSIDE is used to set missing midside node flags in the input maxj topology parameter.
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" static Vdouble coords[9][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,.5,1.} }; static Vint faces[11][4] = { {1,5,3}, {3,5,7,9}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,3,4,2}, {5,8,7,9}, {5,6,8} }; static Vint shapefaces[11] = { SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPETRI, SYS_SHAPEQUAD, SYS_SHAPETRI, SYS_SHAPETRI }; #define MAXJ_SETMISSINGMIDSIDE(a,b) (a) += (1 << (16+(b))) /*---------------------------------------------------------------------- Generate a Mixed Order 3D Volume Mesh ----------------------------------------------------------------------*/ int main() { vis_VolMesh *volmesh; vis_Connect *connect; Vint i; Vint maxi, maxj; Vint numnp, numel; /* create volmesh object */ volmesh = vis_VolMeshBegin (); vis_VolMeshDef (volmesh,9,11); /* create connect object */ connect = vis_ConnectBegin (); vis_ConnectPre (connect,SYS_DOUBLE); vis_ConnectDef (connect,0,0); /* define nodes */ for (i = 0; i < 9; i++) { vis_VolMeshSetNode (volmesh,i+1,coords[i]); } /* define faces */ for (i = 0; i < 11; i++) { maxi = 2; maxj = 0; /* mixed order triangles */ /* maxi is 3 and add bits to maxj for missing midside */ if(i+1 == 2) { maxi = 3; maxj = MAXJ_SETMISSINGMIDSIDE(maxj,0); maxj = MAXJ_SETMISSINGMIDSIDE(maxj,2); } if(i+1 == 10) { maxi = 3; maxj = MAXJ_SETMISSINGMIDSIDE(maxj,0); maxj = MAXJ_SETMISSINGMIDSIDE(maxj,1); } vis_VolMeshSetFace (volmesh,i+1,shapefaces[i],maxi,maxj,faces[i]); } /* set target edge length */ vis_VolMeshSetParamd (volmesh,VIS_MESH_EDGELENGTH,.1); /* generate parabolic tets/pyramids in the interior */ vis_VolMeshSetParami (volmesh,VIS_MESH_MAXI,3); vis_VolMeshWrite (volmesh,SYS_ASCII,"exam61b.vol"); /* generate */ vis_VolMeshGenerate (volmesh,connect); /* print generated nodes and elements */ vis_ConnectNumber (connect,SYS_NODE,&numnp); vis_ConnectNumber (connect,SYS_ELEM,&numel); printf("numnp= %d, numel= %d\n",numnp,numel); vis_ConnectWrite (connect,SYS_NASTRAN_BULKDATA,"exam61b.bdf"); /* end objects */ vis_ConnectEnd (connect); vis_VolMeshEnd (volmesh); return 0; }
#include <stdio.h> #include "base/base.h" #include "vis/vismesh.h" /* 3----3-----4 /. /| / 4 / 2 12 . 11 | / 1....1./...2 7----7-----8 / /| 9 /| 10 / 8 . / 6 / / |. / |/ / 5....5./...6 11---------12 / | . | / | . | / |. | / 9---------10 node numbers 1 through 12 shown on corners edge numbers 1 through 12 shown on edge midsides edges 13 through 18 not shown faces are 1(-z), 2(+z) 3(-y) 4(+y) 5(-x) 6(+x) faces 7 through 12 not shown y | +-- x / z */ /* a 1 by 1 by 2 cube */ static Vdouble xc[12][3] = { {0.,0.,0.}, {1.,0.,0.}, {0.,1.,0.}, {1.,1.,0.}, {0.,0.,1.}, {1.,0.,1.}, {0.,1.,1.}, {1.,1.,1.}, {0.,0.,2.}, {1.,0.,2.}, {0.,1.,2.}, {1.,1.,2.} }; /* triangle connectivity */ static Vint tris[22][3] = { {1,5,3}, {3,5,7}, {4,6,2}, {8,6,4}, {1,2,5}, {5,2,6}, {7,4,3}, {8,4,7}, {1,4,2}, {4,1,3}, {5,8,7}, {5,6,8}, {5,9,7}, {7,9,11}, {8,10,6}, {12,10,8}, {5,6,9}, {9,6,10}, {11,8,7}, {12,8,11}, {9,12,11}, {9,10,12} }; /* triangle preserved edge flags */ static Vint tefl[22][3] = { {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {0,1,1}, {0,1,1}, {1,1,0}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {1,0,1}, {0,1,1}, {0,1,1}, {1,0,1}, {0,1,1}, {1,1,0} }; /* edge associations */ static Vint ted[22][3] = { {9,0,4}, {0,8,12}, {0,10,2}, {1,0,11}, {1,0,9}, {0,10,5}, {0,3,12}, {11,0,7}, {0,2,1}, {0,4,3}, {0,7,8}, {5,6,0}, {9,0,4}, {0,8,12}, {0,10,2}, {1,0,11}, {1,0,9}, {0,10,5}, {0,3,12}, {11,0,7}, {0,7,8}, {5,6,0} }; /* face associations */ static Vint tfa[22] = { 5,5, 6,6, 3,3, 4,4, 1,1, 2,2, 11,11, 9,9, 10,10, 7,7, 8,8 }; /* triangle normals */ /* triangles 13-24, same */ static Vdouble norms[22][3][3] = { {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,-1.}, {0.,0.,-1.}, {0.,0.,-1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{-1.,0.,0.}, {-1.,0.,0.}, {-1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{1.,0.,0.}, {1.,0.,0.}, {1.,0.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,-1.,0.}, {0.,-1.,0.}, {0.,-1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,1.,0.}, {0.,1.,0.}, {0.,1.,0.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}}, {{0.,0.,1.}, {0.,0.,1.}, {0.,0.,1.}} }; /*---------------------------------------------------------------------- Generate a Quad Surface Mesh and Tet Volume Mesh ----------------------------------------------------------------------*/ int main() { vis_SurfMesh *surfmesh; vis_VolMesh *volmesh; vis_Connect *connectsurf, *connectvol; Vint i, j; Vint shape, maxi; Vint numsurfnode, numsurfface; Vint numnp, numel; Vint aid; Vdouble edgelen; /* create SurfMesh object */ surfmesh = vis_SurfMeshBegin (); vis_SurfMeshDef (surfmesh,12,22); /* create Connect object */ connectsurf = vis_ConnectBegin (); vis_ConnectPre (connectsurf,SYS_DOUBLE); vis_ConnectDef (connectsurf,0,0); /* generate linear quad elements on surface */ maxi = 2; shape = VIS_SHAPEQUAD; edgelen = .3; /* define points */ for(i = 0; i < 12; i++) { vis_SurfMeshSetPoint (surfmesh,i+1,xc[i],1); /* set VIS_GEOVERT association to the point id */ vis_SurfMeshSetPointAssoc (surfmesh,VIS_GEOVERT,i+1,i+1); } /* define triangle connectivity */ for(i = 0; i < 22; i++) { vis_SurfMeshSetTri (surfmesh,i+1,tris[i],tefl[i]); vis_SurfMeshSetTriNorm (surfmesh,i+1,norms[i]); for(j = 0; j < 3; j++) { vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOEDGE,i+1,SYS_EDGE,j+1, ted[i][j]); } vis_SurfMeshSetTriAssoc (surfmesh,VIS_GEOFACE,i+1,SYS_FACE,0,tfa[i]); } /* set mesh parameters */ vis_SurfMeshSetParami (surfmesh,SURFMESH_NONMANIFOLD,VIS_ON); vis_SurfMeshSetParami (surfmesh,SURFMESH_INTSURFBACK,VIS_ON); vis_SurfMeshSetParami (surfmesh,VIS_MESH_MAXI,maxi); vis_SurfMeshSetParami (surfmesh,VIS_MESH_SHAPE,shape); vis_SurfMeshSetParamd (surfmesh,VIS_MESH_EDGELENGTH,edgelen); vis_SurfMeshWrite (surfmesh,SYS_ASCII,"exam62.srf"); /* generate */ vis_SurfMeshGenerate (surfmesh,connectsurf); if(vis_SurfMeshError (surfmesh)) { printf("surf mesh generation error\n"); exit(1); } else { printf("surf mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectsurf,SYS_NODE,&numsurfnode); vis_ConnectNumber (connectsurf,SYS_ELEM,&numsurfface); printf(" Number of nodes= %d\n",numsurfnode); printf(" Number of faces= %d\n",numsurfface); /* write generated surf mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectsurf,SYS_NASTRAN_BULKDATA,"exam62_srf.bdf"); /* create VolMesh object */ volmesh = vis_VolMeshBegin (); vis_VolMeshDef (volmesh,numsurfnode,numsurfface); /* Fill VolMesh object with generated surface mesh */ vis_VolMeshConnect (volmesh,connectsurf); /* Define fill regions */ for(i = 1; i <= numsurfface; i++) { vis_ConnectElemAssoc (connectsurf,VIS_GEOBODY,1,&i,&aid); if(aid == 1) { vis_VolMeshSetFaceFill (volmesh,i,VOLMESH_FILL_TET); } else if(aid == 2) { vis_VolMeshSetFaceFill (volmesh,i,VOLMESH_FILL_BOUNDARY); } } /* set mesh parameters */ /* generate parabolic tets */ vis_VolMeshSetParami (volmesh,VIS_MESH_MAXI,3); vis_VolMeshSetParamd (volmesh,VIS_MESH_EDGELENGTH,edgelen); /* create Connect object to hold generated vol mesh */ connectvol = vis_ConnectBegin (); vis_ConnectPre (connectvol,SYS_DOUBLE); vis_ConnectDef (connectvol,0,0); vis_VolMeshWrite (volmesh,SYS_ASCII,"exam62.vol"); /* generate mesh */ vis_VolMeshGenerate (volmesh,connectvol); if(vis_VolMeshError (volmesh)) { printf("vol mesh generation error\n"); exit(1); } else { printf("vol mesh generation complete\n"); } /* print number of surface nodes and elements */ vis_ConnectNumber (connectvol,SYS_NODE,&numnp); vis_ConnectNumber (connectvol,SYS_ELEM,&numel); printf(" Number of nodes= %d\n",numnp); printf(" Number of elems= %d\n",numel); /* write generated mesh in NASTRAN bulk data format */ vis_ConnectWrite (connectvol,SYS_NASTRAN_BULKDATA,"exam62_vol.bdf"); /* end objects */ vis_ConnectEnd (connectsurf); vis_ConnectEnd (connectvol); vis_SurfMeshEnd (surfmesh); vis_VolMeshEnd (volmesh); return 0; }