This example illustrates how to influence the size of elements in the generated 2d mesh by specifying a size function. This process is referred to as scalar paving. The size function is specified using the InterpLinear or InterpIdw classes. The InterpLinear class performs spatial interpolation from points and triangles. This example uses a simple polygon with a set of 5 points and 4 triangles to define a linear size function.
import numpy as np
import geoviews as gv
import holoviews as hv
import pandas as pd
import xarray as xr
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import panel as pn
from shapely.geometry import Polygon
from holoviews.streams import Params
import param
import hvplot.pandas
import hvplot.xarray
import meshing_tools
import xmsmesh
import xmsinterp
hv.extension('bokeh')
def pts_to_dataframe(pts):
np_pts = np.array(pts)
return pd.DataFrame(np_pts, columns=['x', 'y', 'z'])
def tri_list_to_dataframe(tris):
np_tris = np.array(tris)
return pd.DataFrame([(np_tris[x], np_tris[x+1], np_tris[x+2]) for x in range(0, len(tris), 3)], columns=['v0', 'v1', 'v2'])
polygon_points = np.array([
(0, 10,0), (0, 20,0), (0, 30,0), (0, 40,0), (0, 50,0), (0, 60,0), (0, 70,0), (0, 80,0),
(0, 90,0), (0, 100,0), (10, 100,0), (20, 100,0), (30, 100,0), (40, 100,0), (50, 100,0), (60, 100,0),
(70, 100,0), (80, 100,0), (90, 100,0), (100, 100,0), (100, 90,0), (100, 80,0), (100, 70,0), (100, 60,0),
(100, 50,0), (100, 40,0), (100, 30,0), (100, 20,0), (100, 10,0), (100, 0,0), (90, 0,0), (80, 0,0),
(70, 0,0), (60, 0,0), (50, 0,0), (40, 0,0), (30, 0,0), (20, 0,0), (10, 0,0), (0, 0,0)
])
# Display the Polygon
# We are using holoviews instead of geoviews here because we don't need projections for this.
%opts Polygons Points [width=500, height=500]
polygon = Polygon(polygon_points)
polygons = hv.Polygons([polygon,]).redim.range(x=(-15, 115), y=(-15, 115))
points = hv.Points(polygon_points).options(color='black', size=6)
polygons * points
Create linear interpolator for the size function.
df_pts = pts_to_dataframe(((-10, -10, 10), (-10, 110, 10), (110, 110, 10), (110, -10, 10), (60, 70, 1)))
df_tris = tri_list_to_dataframe((0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0))
vert_points = hv.Points(df_pts)
trimesh = hv.TriMesh((df_tris, vert_points))
polygons * points * trimesh
linear = xmsinterp.interpolate.InterpLinear(pts=df_pts.values)
_ = linear.interp_to_pt((0, 0, 0)) # TODO: Fix constructor... This will build the triangles
input_polygon = xmsmesh.meshing.PolyInput(out_poly=polygon_points, size_function=linear)
mesh_io = xmsmesh.meshing.MultiPolyMesherIo(poly_inputs=[input_polygon])
# Generate Mesh
succeded, errors = xmsmesh.meshing.mesh_utils.generate_mesh(mesh_io=mesh_io)
if succeded:
print("Meshing was successful")
else:
print("Meshing errors found:")
for err in errors:
print("\t{}".format(err))
pts, cells = meshing_tools.xmsmesh_to_dataframe(mesh_io.points, mesh_io.cells)
vert_points = hv.Points(pts, vdims=['z'])
trimesh = hv.TriMesh((cells, vert_points))
polygons * points * trimesh.edgepaths.options(line_width=0.5)
Create idw interpolator for the size function.
# use idw as the size function
idw = xmsinterp.interpolate.InterpIdw(pts=df_pts.values)
#mesh_io.poly_inputs[0].size_function = idw
input_polygon = xmsmesh.meshing.PolyInput(out_poly=polygon_points, size_function=idw)
mesh_io = xmsmesh.meshing.MultiPolyMesherIo(poly_inputs=[input_polygon])
# Generate Mesh
succeded, errors = xmsmesh.meshing.mesh_utils.generate_mesh(mesh_io=mesh_io)
if succeded:
print("Meshing was successful")
else:
print("Meshing errors found:")
for err in errors:
print("\t{}".format(err))
pts, cells = meshing_tools.xmsmesh_to_dataframe(mesh_io.points, mesh_io.cells)
vert_points = hv.Points(pts, vdims=['z'])
trimesh = hv.TriMesh((cells, vert_points))
polygons * points * trimesh.edgepaths.options(line_width=0.5)