Transforms
Geometric (e.g. coordinates) transforms are implemented according to the TransformsBase.jl interface. Please read their documentation for more details.
Meshes.GeometricTransform
— TypeGeometricTransform
A method to transform the geometry (e.g. coordinates) of objects. See https://en.wikipedia.org/wiki/Geometric_transformation.
Meshes.CoordinateTransform
— TypeCoordinateTransform
A method to transform the coordinates of objects. See https://en.wikipedia.org/wiki/List_of_common_coordinate_transformations.
Some transforms have an inverse that can be created with the inverse
function. The function isinvertible
can be used to check if a transform is invertible.
TransformsBase.inverse
— FunctionTransformsBase.isinvertible
— Functionisinvertible(transform)
Tells whether or not the transform
is invertible, i.e. whether it implements the inverse
function. Defaults to false
for new transform types.
Transforms can be invertible in the mathematical sense, i.e., there exists a one-to-one mapping between input and output spaces.
See also inverse
, isrevertible
.
Rotate
Meshes.Rotate
— TypeRotate(R)
Rotate geometry or domain with rotation R
from Rotations.jl.
Rotate(u, v)
Rotation mapping the axis directed by u
to the axis directed by v
. More precisely, it maps the plane passing through the origin with normal vector u
to the plane passing through the origin with normal vector v
.
Rotate(θ)
Rotate the 2D geometry or domain by angle θ
, in radians, using the Angle2d
rotation.
Examples
Rotate(one(RotXYZ{Float64})) # identity rotation
Rotate(AngleAxis(0.2, 1.0, 0.0, 0.0)) # rotate 0.2 radians around X axis
Rotate(rand(QuatRotation{Float64})) # random rotation
Rotate(Vec(1, 0, 0), Vec(1, 1, 1)) # rotation from (1, 0, 0) to (1, 1, 1)
Rotate(π / 2) # 2D rotation with angle in radians
grid = CartesianGrid(10, 10)
mesh = grid |> Rotate(π/4)
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], mesh)
fig
Translate
Meshes.Translate
— TypeTranslate(o₁, o₂, ...)
Translate coordinates of geometry or mesh by given offsets o₁, o₂, ...
.
grid = CartesianGrid(10, 10)
mesh = grid |> Translate(10., 20.)
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], mesh)
fig
Scale
Meshes.Scale
— TypeScale(s₁, s₂, ...)
Scale geometry or domain with strictly positive scaling factors s₁, s₂, ...
.
Examples
Scale(1.0, 2.0, 3.0)
grid = CartesianGrid(10, 10)
mesh = grid |> Scale(2., 3.)
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], mesh)
fig
Affine
Meshes.Affine
— TypeAffine(A, b)
Affine transform Ax + b
with matrix A
and vector b
.
Examples
Affine(AngleAxis(0.2, 1.0, 0.0, 0.0), [-2, 2, 2])
Affine(Angle2d(π / 2), SVector(2, -2))
Affine([0 -1; 1 0], [-2, 2])
using Rotations: Angle2d
grid = CartesianGrid(10, 10)
mesh = grid |> Affine(Angle2d(π/4), [10., 20.])
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], mesh)
fig
Stretch
Meshes.Stretch
— TypeStretch(s₁, s₂, ...)
Stretch geometry or domain outwards with strictly positive scaling factors s₁, s₂, ...
.
Examples
Stretch(1.0, 2.0, 3.0)
grid = CartesianGrid(10, 10)
mesh = grid |> Stretch(2., 3.)
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], mesh)
fig
StdCoords
Meshes.StdCoords
— TypeStdCoords()
Standardize coordinates of all geometries to the interval [-0.5, 0.5]
.
Examples
julia> CartesianGrid(10, 10) |> StdCoords()
10×10 CartesianGrid{2,Float64}
minimum: Point(-0.5, -0.5)
maximum: Point(0.5, 0.5)
spacing: (0.1, 0.1)
# Cartesian grid with coordinates [0,10] x [0,10]
grid = CartesianGrid(10, 10)
# scale coordinates to [-1,1] x [-1,1]
mesh = grid |> StdCoords()
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], mesh)
fig
Proj
Meshes.Proj
— TypeProj(CRS)
Proj(code)
Convert the coordinates of geometry or domain to a given coordinate reference system CRS
or EPSG/ESRI code
.
Optionally, the transform samples the boundary
of polytopes, if this option is true
, to handle distortions that occur in manifold conversions.
Examples
Proj(Polar)
Proj(WebMercator)
Proj(Mercator{WGS84Latest})
Proj(EPSG{3395})
Proj(ESRI{54017})
Notes
- By default, only the vertices of the polytopes are transformed, disregarding distortions that occur in manifold conversions. To handle this case, use
TransformedGeometry
.
# load coordinate reference system
using CoordRefSystems: Polar
# triangle with Cartesian coordinates
triangle = Triangle((0, 0), (1, 0), (1, 1))
# reproject to polar coordinates
triangle |> Proj(Polar)
Triangle
├─ Point(ρ: 0.0 m, ϕ: 0.0 rad)
├─ Point(ρ: 1.0 m, ϕ: 0.0 rad)
└─ Point(ρ: 1.4142135623730951 m, ϕ: 0.7853981633974483 rad)
Morphological
Meshes.Morphological
— TypeMorphological(fun)
Morphological transform given by a function fun
that maps the coordinates of a geometry or a domain to new coordinates (coords -> newcoords
).
Examples
ball = Ball((0, 0), 1)
ball |> Morphological(c -> Cartesian(c.x + c.y, c.y, c.x - c.y))
triangle = Triangle(Point(LatLon(0, 0)), Point(LatLon(0, 45)), Point(LatLon(45, 0)))
triangle |> Morphological(c -> LatLonAlt(c.lat, c.lon, 0.0m))
Notes
- By default, only the vertices of the polytopes are transformed, disregarding distortions that occur in manifold conversions. To handle this case, use
TransformedGeometry
.
# triangle with Cartesian coordinates
triangle = Triangle((0, 0), (1, 0), (1, 1))
# transform triangle coordinates
triangle |> Morphological(c -> Cartesian(c.x, c.y, zero(c.x)))
Triangle
├─ Point(x: 0.0 m, y: 0.0 m, z: 0.0 m)
├─ Point(x: 1.0 m, y: 0.0 m, z: 0.0 m)
└─ Point(x: 1.0 m, y: 1.0 m, z: 0.0 m)
LengthUnit
Meshes.LengthUnit
— TypeLengthUnit(unit)
Convert the length unit of coordinates of a geometry or domain to unit
.
Examples
LengthUnit(u"cm")
LengthUnit(u"km")
using Unitful: m, cm
# convert meters to centimeters
Point(1m, 2m, 3m) |> LengthUnit(cm)
Point with Cartesian{NoDatum} coordinates
├─ x: 100.0 cm
├─ y: 200.0 cm
└─ z: 300.0 cm
Shadow
Meshes.Shadow
— TypeShadow(dims)
Project the geometry or domain onto the given dims
, producing a "shadow" of the original object.
Examples
Shadow(:xy)
Shadow("xz")
Shadow(1, 2)
Shadow((1, 3))
ball = Ball((0, 0, 0), 1)
disk = ball |> Shadow("xy")
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], ball)
viz(fig[1,2], disk)
fig
Slice
Meshes.Slice
— TypeSlice(x=(xmin, xmax), y=(ymin, ymax), z=(zmin, zmax))
Slice(lat=(latmin, latmax), lon=(lonmin, lonmax))
Retain the domain elements within x
limits [xmax
,xmax
], y
limits [ymax
,ymax
] and z
limits [zmin
,zmax
] in length units (default to meters), or within lat
limits [latmin
,latmax
] and lon
limits [lonmin
,lonmax
] in degree units.
Examples
Slice(x=(1000km, 3000km))
Slice(x=(1000km, 2000km), y=(2000km, 5000km))
Slice(lon=(0°, 90°))
Slice(lon=(0°, 45°), lat=(0°, 45°))
grid = CartesianGrid(10, 10)
subgrid = grid |> Slice(x=(1.5, 6.5), y=(3.5, 8.5))
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], grid)
viz(fig[1,2], subgrid)
fig
Repair
Meshes.Repair
— TypeRepair(K)
Perform repairing operation with code K
.
Available operations
- K = 0: duplicated vertices and faces are removed
- K = 1: unused vertices are removed
- K = 2: non-manifold faces are removed
- K = 3: degenerate faces are removed
- K = 4: non-manifold vertices are removed
- K = 5: non-manifold vertices are split by threshold
- K = 6: close vertices are merged (given a radius)
- K = 7: faces are coherently oriented
- K = 8: zero-area ears are removed
- K = 9: rings of polygon are sorted
- K = 10: outer rings of polygon are expanded
- K = 11: rings of polygon are coherently oriented
- K = 12: degenerate rings of polygon are removed
Examples
# remove duplicates and degenerates
mesh |> Repair(0) |> Repair(3)
# mesh with unreferenced point
points = [(0, 0, 0), (0, 0, 1), (5, 5, 5), (0, 1, 0), (1, 0, 0)]
connec = connect.([(1, 2, 4), (1, 2, 5), (1, 4, 5), (2, 4, 5)])
mesh = SimpleMesh(points, connec)
rmesh = mesh |> Repair(1)
4 SimpleMesh
4 vertices
├─ Point(x: 0.0 m, y: 0.0 m, z: 0.0 m)
├─ Point(x: 0.0 m, y: 0.0 m, z: 1.0 m)
├─ Point(x: 0.0 m, y: 1.0 m, z: 0.0 m)
└─ Point(x: 1.0 m, y: 0.0 m, z: 0.0 m)
4 elements
├─ Triangle(1, 2, 3)
├─ Triangle(1, 2, 4)
├─ Triangle(1, 3, 4)
└─ Triangle(2, 3, 4)
Bridge
Meshes.Bridge
— TypeBridge(δ=0)
Transform polygon with holes into a single outer ring via bridges of given width δ
as described in Held 1998.
References
# polygon with two holes
outer = [(0, 0), (1, 0), (1, 1), (0, 1)]
hole1 = [(0.2, 0.2), (0.2, 0.4), (0.4, 0.4), (0.4, 0.2)]
hole2 = [(0.6, 0.2), (0.6, 0.4), (0.8, 0.4), (0.8, 0.2)]
poly = PolyArea([outer, hole1, hole2])
# polygon with single outer ring
bpoly = poly |> Bridge(0.01)
fig = Mke.Figure(size = (800, 400))
viz(fig[1,1], poly)
viz(fig[1,2], bpoly)
fig
Smoothing
Meshes.LambdaMuSmoothing
— TypeLambdaMuSmoothing(n, λ, μ)
Perform n
smoothing iterations with parameters λ
and μ
.
See also LaplaceSmoothing
, TaubinSmoothing
.
References
- Taubin, G. 1995. Curve and Surface Smoothing without Shrinkage
Meshes.LaplaceSmoothing
— FunctionLaplaceSmoothing(n, λ=0.5)
Perform n
iterations of Laplace smoothing with parameter λ
.
References
- Sorkine, O. 2005. Laplacian Mesh Processing
Meshes.TaubinSmoothing
— FunctionTaubinSmoothing(n, λ=0.5)
Perform n
iterations of Taubin smoothing with parameter 0 < λ < 1
.
References
- Taubin, G. 1995. Curve and Surface Smoothing without Shrinkage
using PlyIO
# helper function to read *.ply files
function readply(fname)
ply = load_ply(fname)
x = ply["vertex"]["x"]
y = ply["vertex"]["y"]
z = ply["vertex"]["z"]
points = Point.(x, y, z)
connec = [connect(Tuple(c.+1)) for c in ply["face"]["vertex_indices"]]
SimpleMesh(points, connec)
end
# download mesh from the web
file = download(
"https://raw.githubusercontent.com/juliohm/JuliaCon2021/master/data/beethoven.ply"
)
# read mesh from disk
mesh = readply(file)
# smooth mesh with 30 iterations
smesh = mesh |> TaubinSmoothing(30)
fig = Mke.Figure(size = (800, 1200))
viz(fig[1,1], mesh)
viz(fig[2,1], smesh)
fig