GeomProcess
The GeMA Geometry Process Plugin
Loading...
Searching...
No Matches
GeomProcess

Index:

Creating new meshes

geom.extractMeshFromMeshBorders(srcMesh, newMeshName, options)
Description: Given a source mesh, traverses the mesh border extracting border sides. The extracted set will be composed of mesh edges for input surface meshes or mesh faces for input volume meshes. Sides can be filtered by a user function, exactly like the one used for extracting boundary edge or face data in a mesh definition using the standard GeMA mesh plugin. The final set of sides is used to create a new mesh. If the source mesh is a surface mesh, the new mesh will be composed of bar elements. If it is a volume mesh, it will be composed of quad3d and/or tri3d elements. The new mesh coordinate dimension and unit are equal to the input mesh. All types of elements from the input mesh can be processed, including quadratic faces and interface element faces. Notice that if the set of sides includes "aperture" faces from interface elements, extra interpolated nodes might need to be created. Hex27 element faces are transformed into quad3d8 elements and the mid face node is ignored. The consistency of the new mesh orientation is guaranteed, and for source volume meshes, it is possible to create a topology for the extracted surface mesh.
Parameters: srcMesh The source mesh. Accepts either a mesh name or a mesh object.
newMeshName The id for the new mesh. Must be unique.
options An optional table filled with additional options used to filter the set of sides and to define special characteristics for the created mesh. It can also request the creation of a spatial index for the new mesh or to project the mesh onto the XY plane. Available option fields are:
- filter: A filter function that, when defined, will be applied to every side in the src mesh to define if it should be added to the new mesh or not. It is a function that receives a single table as input, containing information about the side, and should return true if the side should be added to the mesh or false if not. See the standard GeMA mesh plugin documentation for the information provided by the filter input parameter. If no filter is provided, all sides will be added to the result mesh.
- border: If different from nil, restricts the extracted sides to the given mesh border, even if no filter was defined. If a filter function was also defined, it will be called only for sides on the given border. Its value should be either the border index directly or a table with a cell id and a side index pair, defining the extraction border to be the one that contains that cell / side pair. Default is nil.
- pluginType: The plugin type that will be used to create the new mesh. Default is "GemaMesh.elem".
- attributes: A table with additional attributes that are sent to the mesh creation plugin to properly initialize the new mesh. Can be used to tweak the new mesh definition. When using the standard mesh plugin, enables setting mesh options such as the description, ghost nodes support, topology flags, etc. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
- addToModel: Flag defining if the new mesh should be added to the simulation model or not. Also applied to the spatial index if createIndex is true. Default is true.
- saveSrc: Flag defining if the srcCellId and srcSide cell attributes should be added to the new mesh. Default is false.
- projected: Flag defining if the new mesh should have its nodes projected on the XY plane. Together with the createIndex option, it helps preparing input parameters for calling geom.burialDepth(). Default is false.
- createIndex: Flag defining if a spatial index object should also be created for the new mesh. Ignored if projected is not true. Default is false.
- indexName: The index object name when createIndex is true. Default is the mesh name + "_sindex".
- indexPluginType: The plugin used to create the spatial index object when createIndex is true. Default is "MmProcess.cell".
- indexAttributes: A table with additional attributes that are sent to the spatial index plugin to properly initialize the new index. Can be used to tweak the new index definition. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
Returns: Returns the newly created mesh object. If the createIndex option is true, also returns the index object. On errors, returns nil.

Example:

-- Creates a new mesh extracting the top surface using as filter criteria that the unit normal
-- component on the Z direction is greater than 0.7, so accepting a top surface with some slight
-- curvature.
local extractOptions = {
filter = function(d) return d.normal(3) > 0.7 end,
saveSrc = true,
attributes = { description = "My new mesh", coordinateFormat = "6.4f", topologyCheckOptions = "full"}, -- Some extra configuration for the mesh plugin
}
local topBorderMesh = geom.extractMeshFromMeshBorders('mesh', 'topBorderMesh', extractOptions)


geom.extractMeshFromMeshBoundary(boundaryObject, newMeshName, options)
Description: Given a cell boundary object (usually returned by a call to mesh:cellBoundaryGroups()), creates a new mesh from the given border sides. If the input is an edge boundary, the new mesh will be composed of bar elements. If it is a face boundary, it will be composed of quad3d and/or tri3d elements. The new mesh coordinate dimension and unit are equal to the mesh that owns the given boundary. All types of elements from the boundary can be processed, including quadratic faces and interface element faces. Notice that if the set of sides includes "aperture" faces from interface elements, extra interpolated nodes might need to be created. Hex27 element faces are transformed into quad3d8 elements and the mid face node is ignored. The consistency of the new mesh orientation is guaranteed, and for face boundaries, it is possible to create a topology for the extracted surface mesh.
Parameters: boundaryObject The cell boundary object.
newMeshName The id for the new mesh. Must be unique.
options An optional table filled with additional options used to define special characteristics for the created mesh. It can also request the creation of a spatial index for the new mesh or to project the mesh onto the XY plane. Available option fields are:
- pluginType: The plugin type that will be used to create the new mesh. Default is "GemaMesh.elem".
- attributes: A table with additional attributes that are sent to the mesh creation plugin to properly initialize the new mesh. Can be used to tweak the new mesh definition. When using the standard mesh plugin, enables setting mesh options such as the description, ghost nodes support, topology flags, etc. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
- addToModel: Flag defining if the new mesh should be added to the simulation model or not. Also applied to the spatial index if createIndex is true. Default is true.
- saveSrc: Flag defining if the srcCellId and srcSide cell attributes should be added to the new mesh. Default is false.
- projected: Flag defining if the new mesh should have its nodes projected on the XY plane. Together with the createIndex option, it helps preparing input parameters for calling geom.burialDepth(). Default is false.
- createIndex: Flag defining if a spatial index object should also be created for the new mesh. Ignored if projected is not true. Default is false.
- indexName: The index object name when createIndex is true. Default is the mesh name + "_sindex".
- indexPluginType: The plugin used to create the spatial index object when createIndex is true. Default is "MmProcess.cell".
- indexAttributes: A table with additional attributes that are sent to the spatial index plugin to properly initialize the new index. Can be used to tweak the new index definition. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
Returns: Returns the newly created mesh object. If the createIndex option is true, also returns the index object. On errors, returns nil.

Example:

-- Creates a new mesh from the faces in the "topBorder" boundary, as defined in the model
local topBoundary = mesh:cellBoundaryGroups()['topBorder']
local topBoundaryMesh = geom.extractMeshFromMeshBoundary(topBoundary, 'topBoundaryMesh', {saveSrc = true})


geom.extractProjectedMeshFromMesh(srcSurfaceMesh, newMeshName, options)
Description: Given a source surface mesh filled with 3d quads and / or triangles, projects the mesh elements on the XY plane and returns a new mesh with them. This method is often used to prepare the spatial index needed for retrieving burial depths.
Parameters: srcSurfaceMesh The source mesh. Accepts either a mesh name or a mesh object. Must be a surface mesh with 3d quad and/or tri cells.
newMeshName The id for the new mesh. Must be unique.
options An optional table filled with additional options used to define special characteristics for the created mesh. It can also request the creation of a spatial index for the new mesh. Available option fields are:
- pluginType: The plugin type that will be used to create the new mesh. Default is "GemaMesh.elem".
- attributes: A table with additional attributes that are sent to the mesh creation plugin to properly initialize the new mesh. Can be used to tweak the new mesh definition. When using the standard mesh plugin, enables setting mesh options such as the description, ghost nodes support, topology flags, etc. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
- addToModel: Flag defining if the new mesh should be added to the simulation model or not. Also applied to the spatial index if createIndex is true. Default is true.
- createIndex: Flag defining if a spatial index object should also be created for the new mesh. Default is false.
- indexName: The index object name when createIndex is true. Default is the mesh name + "_sindex".
- indexPluginType: The plugin used to create the spatial index object when createIndex is true. Default is "MmProcess.cell".
- indexAttributes: A table with additional attributes that are sent to the spatial index plugin to properly initialize the new index. Can be used to tweak the new index definition. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
Returns: Returns the newly created mesh object. If the createIndex option is true, also returns the index object. On errors, returns nil.

Example:

-- Creates a new projected mesh + index from a mesh extracted from the faces in the "topBorder" boundary, as defined in the model
-- The projected mesh is not added to the simulation model since it will be used only by the spatial index
local topBoundary = mesh:cellBoundaryGroups()['topBorder']
local topBoundaryMesh = geom.extractMeshFromMeshBoundary(topBoundary, 'topBoundaryMesh', {saveSrc = true})
local projOptions = {createIndex = true, indexName = 'myIndex', addToModel = false}
local projMeshFromMesh, projMeshIndex = geom.extractProjectedMeshFromMesh(topBoundaryMesh, 'projMeshFromMesh', projOptions)


geom.createSimpleMesh(nodeList, cellType, cellList, newMeshName, options)
Description: Creates a new mesh with node coordinates and cell incidences provided by the given Lua tables. It is equivalent to calling modelData:addNewEmptyMesh() followed by calls to mesh:addNodes(), mesh:addCells() and loops for initializing the new mesh node coordinates and cell incidences. Can also be used for creating node only meshes, provided that the options parameter specifies a non default pluginType for a node mesh only.
Parameters: nodeList A table with the set of node coordinates. Each entry should be a sub-table with the coordinates of one node. All sub-tables should have the same size and the size of the first one defines the mesh coordinates dimension.
cellType If the created mesh is an homogeneous cell mesh, this parameter should be filled with the cell type string (see Element types for the available cell types). If not, we are creating a node only mesh or an heterogeneous cell mesh and it should be equal to nil.
cellList A table with cell incidences for a cell mesh or nil for a node only mesh. Each entry is a sub-table with the nodal incidences for one cell. If the cell set is homogeneous, the cell type should be provided by the cellType parameter and the incidence sub-tables should provide only the node indices for each element. Its size must be equal to the number of nodes for that cell type. For heterogeneous meshes, each sub-table should begin with the cell type string, followed by the nodal incidence list.
newMeshName The id for the new mesh. Must be unique.
options An optional table filled with additional options used to define special characteristics for the created mesh. Available option fields are:
- pluginType: The plugin type that will be used to create the new mesh. Default is "GemaMesh.elem".
- attributes: A table with additional attributes that are sent to the mesh creation plugin to properly initialize the new mesh. Can be used to tweak the new mesh definition. When using the standard mesh plugin, enables setting mesh options such as the description, coordinate unit, ghost nodes support, topology flags, etc. See the plugin documentation. Important: fields whose values are sub-tables are not supported at the moment.
- addToModel: Flag defining if the new mesh should be added to the simulation model or not. Default is true.
Returns: Returns the newly created mesh object. On errors, returns nil.

Example:

-- Creates a new homogeneous mesh filled with the set of nodes and cells difined by the nodeList and cellList tables
-- See the example for fillEmptyMesh() for a cellList with heterogeneous elements
local nodeList = {
{0, 0}, {1, 0}, {2, 0}, {3, 0},
{0, 1}, {1, 1}, {2, 1}, {3, 1},
{0, 2}, {1, 2}, {2, 2}, {3, 2},
}
local cellList = {
{1, 2, 6, 5},
{2, 3, 7, 6},
{3, 4, 8, 7},
{5, 6, 10, 9},
{6, 7, 11, 10},
{7, 8, 12, 11},
}
local newMesh = geom.createSimpleMesh(nodeList, 'quad4', cellList, 'newMesh')


geom.fillEmptyMesh(mesh, nodeList, cellType, cellList)
Description: Given an empty mesh, fills it with node coordinates and cell incidences provided by the given Lua tables. It is equivalent to calling mesh:addNodes() and mesh:addCells(), followed by loops for initializing the new mesh node coordinates and cell incidences.
Parameters: mesh The mesh to be filled. Accepts either a mesh name or a mesh object. Must be an empty mesh.
nodeList A table with the set of node coordinates. Each entry should be a sub-table with the coordinates of one node and its size should be equal to the mesh coordinates dimension.
cellType Should be nil if the given mesh is a node only mesh. For cell meshes, if the added cells are homogeneous, this parameter should be filled with the cell type string (see Element types for the available cell types). Otherwise, the cell set is heterogeneous and it should be equal to nil.
cellList A table with cell incidences for a cell mesh or nil for a node only mesh. Each entry is a sub-table with the nodal incidences for one cell. If the cell set is homogeneous, the cell type should be provided by the cellType parameter and the incidence sub-tables should provide only the node indices for each element. Its size must be equal to the number of nodes for that cell type. For heterogeneous meshes, each sub-table should begin with the cell type string, followed by the nodal incidence list. Either way, if the mesh is tied to property sets, the incidence list should be followed by the property set indices for that cell, in the correct property sets mesh order (the same order in which property sets where attached to the mesh).
Returns: Returns true if the mesh was filled successfully or false if not.

Example:

-- Fills the empty mesh 'mesh', created at the model file, with the set of nodes and heterogeneous cells
-- difined by the nodeList and cellList tables.
-- See the example for createSimpleMesh() for a cellList with homogeneous elements
local nodeList = {
{0, 0}, {1, 0}, {2, 0}, {3, 0},
{0, 1}, {1, 1}, {2, 1}, {3, 1},
{0, 2}, {1, 2}, {2, 2}, {3, 2},
}
local cellList = {
{'quad4', 1, 2, 6, 5},
{'tri3', 2, 3, 6},
{'tri3', 3, 7, 6},
{'quad4', 3, 4, 8, 7},
{'tri3', 6, 7, 10},
{'tri3', 7, 11, 10},
{'quad4', 5, 6, 10, 9},
{'quad4', 7, 8, 12, 11},
}
local ok = geom.fillEmptyMesh('mesh', nodeList, nil, cellList)


geom.releaseExtractedMesh(newMesh)
Description: Releases the mesh object received as parameter, removing the mesh from GeMA. The given mesh should be a mesh created dynamically by one of the following functions: geom.extractMeshFromMeshBorders(), geom.extractMeshFromMeshBoundary(), geom.extractProjectedMeshFromMesh(), geom.createSimpleMesh() or modelData:addNewEmptyMesh(). It can work with meshes that where added to the model or not.
IMPORTANT: The released mesh can not be referenced in any way by another GeMA object, such as a physics, a fem solver, an interpolator, a spatial index, etc. Any remaining Lua references to it must not be used again after the removal. This is an inherently UNSAFE function, mainly provided so that test code can create and destroy meshes as a way to handle the 8 mesh limit. Use with CARE.
Parameters: newMesh - The mesh object to be released.
Returns: Nothing.

Example:

-- Creates a new mesh from the faces in the "topBorder" boundary, as defined in the model
local topBoundary = mesh:cellBoundaryGroups()['topBorder']
local topBoundaryMesh = geom.extractMeshFromMeshBoundary(topBoundary, 'topBoundaryMesh', {saveSrc = true})
-- Do something with the mesh...
gem.releaseExtractedMesh(topBoundaryMesh)


Burial depth

geom.burialDepth(seaFloorMesh, seaFloorCoordAc, projSeaFloorIndex, point)
Description: Given a 3d point coordinate, returns its burial depth by finding the point projection onto the sea floor surface mesh and returning the absolute depth difference. If the x, y coordinate is outside the sea floor mesh domain, returns nil. The image below ilustrates the calculation process. To calculate the burial depth of a point p = (x, y, z), we first find the cell containing (x, y) in the projected sea floor mesh by using the provided spatial index. This cell should have a 1 to 1 mapping with the 3d sea floor mesh. From that 3d sea floor mesh cell, we collect the z coordinates of the cell's nodes and calculate its average 'a'. The function then returns abs(z-a).
Parameters: seaFloorMesh The source mesh with the sea floor depth representation on the Z coordinate. Accepts either a mesh name or a mesh object. Must be a surface mesh with 3d quad and/or tri cells. If the sea floor mesh coincides with the top surface of the main model mesh, it can be extracted with calls to geom.extractMeshFromMeshBorders() or geom.extractMeshFromMeshBoundary().
seaFloorCoordAc An accessor for the sea floor mesh node coordinates (see mesh:nodeCoordAccessor()). Notice that this accessor should not define unit conversions.
projSeaFloorIndex The spatial index object that will be used to efficiantly locate the sea floor mesh cell that contains the query point. Must implement the "containingCell" capability. The index should be created over a mesh storing the projection of the sea floor mesh onto the XY plane. This projected mesh cells should have a 1 to 1 mapping with the 3d sea floor mesh, having equivalent cell ids. The projected mesh and associated index can be created by calls to geom.extractMeshFromMeshBorders(), geom.extractMeshFromMeshBoundary() or geom.extractProjectedMeshFromMesh(). Just make sure to use the correct options for that.
point The 3d coordinates of the queried point in the same unit as the standard mesh unit. Can be either a Lua table with the x, y and z coordinates or a vector object filled with them.
Returns: Returns the calculated burial depth or nil if the given point coordinates are outside the domain of the projected sea floor mesh used to build the given spatial index.

Example:

-- Creates the sea floor mesh from the faces in the "topBorder" boundary, as defined in the model
local topBoundary = mesh:cellBoundaryGroups()['topBorder']
local seaFloorMesh = geom.extractMeshFromMeshBoundary(topBoundary, 'seaFloorMesh')
local seaFloorAc = seaFloorMesh:nodeCoordAccessor()
-- Creates a new sea floor projected mesh + associated spatial index from the sea floor mesh
-- The mesh and the index are not added to the simulation model since they will be used only
-- for burial depth retrieval
local projOptions = {createIndex = true, indexName = 'seaFloorProjIndex', addToModel = false}
local projSeaFloorMesh, projSeaFloorIndex = geom.extractProjectedMeshFromMesh(seaFloorMesh, 'projSeaFloorMesh', projOptions)
-- Print burial depth for a set of coordinates
for _, x in ipairs{-1, 0.5, 2, 2.5, 4.5, 6.5, 10, 11} do
for _, y in ipairs{-1, 0.5, 2, 2.5, 10, 11} do
for _, z in ipairs{1000.0, 1200.0, 1300.0} do
local bd = geom.burialDepth(seaFloorMesh, seaFloorAc, projSeaFloorIndex, {x, y, z})
if bd == nil then
print('Coordinate is outside the sea floor domain')
else
print('Burial depth is ', bd)
end
end
end
end


Mesh quality operations

geom.isMeshValid(mesh, print, tolerance)
Description:
Parameters: mesh
print
tolerance
Returns:


geom.isMeshQualityGT(mesh, minQuality)
Description:
Parameters: mesh
minQuality
Returns:


geom.meshQualityHistogram(mesh, numBins)
Description:
Parameters: mesh
numBins
Returns:


Other geometric operations

geom.getConvexHull(coordAccessor, inclusive)
Description: Get the 2D convex hull of all the nodes in a given mesh. The implementation is based on https://www.algorithmist.com/index.php/Monotone_Chain_Convex_Hull.cpp algorithm.
Parameters: coordAccessor An accessor for the mesh node coordinates (see mesh:nodeCoordAccessor()).
inclusive When set to true, the returned list will contain the potential collinear nodes. In this case a home-made and not-so-fast algorithm is used.
Returns: The returning list of CCW ordered node ids defining the convex hull.


geom.pointInConvexPolygon(pointCoord, coordAccessor, nodeIds)
Description: Check if a 2D point is inside or outside the convex polygon delimited by a set of mesh nodes.
Parameters: pointCoord A lua table with the coordinates of the point.
coordAccessor An accessor for the mesh node coordinates (see mesh:nodeCoordAccessor()).
nodeIds The list of CCW ordered node ids defining the convex polygon.
Important: no check is done in regard to the convexity of the input polygon!
Returns: true if the point is inside, or false otherwise.

Example using the two previous functions:

-- Check that all the nodes of a mesh are inside the mesh convex hull
local mesh = modelData:mesh('mesh')
local crdAc = mesh:nodeCoordAccessor()
local convexHull = geom.getConvexHull(crdAc)
for i=1, mesh:numNodes() do
local point = crdAc:value(i)
assert(geom.pointInConvexPolygon(point, crdAc, convexHull))
end


geom.delaunayTriangulation(coordAccessor)
Description: Compute the 2D delaunay triangulation of all the nodes in a given mesh. The implementation uses the https://github.com/mapbox/delaunator code.
Parameters: coordAccessor - An accessor for the mesh node coordinates (see mesh:nodeCoordAccessor()).
Returns: Three equal-size lua tables which size is equal to the number of triangles in the computed triangulation. The returned tables respectively store the first, second and third node id of each triangle.

Example:

-- Build a triangle mesh starting from a grid-based set of points
-- and its corresponding delaunay triangulation
-- define the grid corners
local xmin, xmax = -10, 10 -- left / right
local ymin, ymax = -10, 10 -- bottom / top
-- number of grid subdivisions in each direction
local ni, nj = 10, 10
-- compute point coordinates as part of a regular grid
local v = {}
for i=0, ni do
local x = xmin + (i/ni) * (xmax-xmin)
for j=0, nj do
local y = ymin + (j/nj) * (ymax-ymin)
table.insert(v, Vector({x, y}))
end
end
assert(#v == (ni+1)*(nj+1))
-- empty mesh!
local mesh = modelData:mesh('mesh')
local crdAcc = mesh:nodeCoordAccessor()
-- add nodes to mesh and set its coordinates
mesh:addNodes(#v)
for i=1, #v do
crdAcc:setValue(i, v[i])
end
-- process delaunay triangulation
local t1, t2, t3 = geom.delaunayTriangulation(crdAcc)
-- add triangles to mesh and set its nodes incidence
mesh:addCells({tri3 = #t1})
for i=1, mesh:numCells() do
local cell = mesh:cell(i)
cell:setNodes({t1[i], t2[i], t3[i]}, mesh)
end
-- print mesh geometry
mesh:printValues()

GeMA project main page