Merge pull request #3745 from t-bltg/mesh3d
Move mesh3d triangle to utils - gaston: implement :mesh3d
This commit is contained in:
commit
c171cd0cf5
@ -47,12 +47,14 @@ end
|
||||
|
||||
function _update_min_padding!(sp::Subplot{GastonBackend})
|
||||
sp.minpad = 0mm, 0mm, 0mm, 0mm
|
||||
nothing
|
||||
end
|
||||
|
||||
function _update_plot_object(plt::Plot{GastonBackend})
|
||||
# respect the layout ratio
|
||||
dat = gaston_multiplot_pos_size(plt.layout, (0, 0, 1, 1))
|
||||
gaston_multiplot_pos_size!(dat)
|
||||
nothing
|
||||
end
|
||||
|
||||
for (mime, term) ∈ (
|
||||
@ -224,6 +226,9 @@ function gaston_add_series(plt::Plot{GastonBackend}, series::Series)
|
||||
length(y) == size(z, 1) + 1 && (y = @view y[1:end-1])
|
||||
end
|
||||
end
|
||||
if st == :mesh3d
|
||||
x, y, z = mesh3d_triangles(x, y, z, series[:connections])
|
||||
end
|
||||
for sc ∈ gaston_seriesconf!(sp, series, 1, true)
|
||||
push!(curves, Gaston.Curve(x, y, z, nothing, sc))
|
||||
end
|
||||
@ -302,7 +307,7 @@ function gaston_seriesconf!(sp::Subplot{GastonBackend}, series::Series, i::Int,
|
||||
palette = gaston_palette(series[:seriescolor])
|
||||
gsp.axesconf *= "\nset palette model RGB defined $palette"
|
||||
st == :heatmap && (gsp.axesconf *= "\nset view map")
|
||||
elseif st == :wireframe
|
||||
elseif st ∈ (:wireframe, :mesh3d)
|
||||
lc, dt, lw = gaston_lc_ls_lw(series, clims, i)
|
||||
push!(curveconf, "w lines lc $lc dt $dt lw $lw")
|
||||
elseif st == :quiver
|
||||
@ -467,14 +472,6 @@ end
|
||||
# Helpers
|
||||
# --------------------------------------------
|
||||
|
||||
function gaston_font(f; rot=true, align=true, color=true, scale=1)
|
||||
font = String["font '$(f.family),$(round(Int, scale * f.pointsize))'"]
|
||||
align && push!(font, "$(gaston_halign(f.halign))")
|
||||
rot && push!(font, "rotate by $(f.rotation)")
|
||||
color && push!(font, "textcolor $(gaston_color(f.color))")
|
||||
return join(font, " ")
|
||||
end
|
||||
|
||||
gaston_halign(k) = (left=:left, hcenter=:center, right=:right)[k]
|
||||
gaston_valign(k) = (top=:top, vcenter=:center, bottom=:bottom)[k]
|
||||
|
||||
@ -492,6 +489,14 @@ gaston_mk_ms_mc(series::Series, clims, i::Int) = (
|
||||
gaston_color(get_markercolor(series, clims, i), get_markeralpha(series, i)),
|
||||
)
|
||||
|
||||
function gaston_font(f; rot=true, align=true, color=true, scale=1)
|
||||
font = String["font '$(f.family),$(round(Int, scale * f.pointsize))'"]
|
||||
align && push!(font, "$(gaston_halign(f.halign))")
|
||||
rot && push!(font, "rotate by $(f.rotation)")
|
||||
color && push!(font, "textcolor $(gaston_color(f.color))")
|
||||
return join(font, " ")
|
||||
end
|
||||
|
||||
function gaston_palette(gradient)
|
||||
palette = String[]; n = -1
|
||||
for rgba ∈ gradient # FIXME: naive conversion, inefficient ?
|
||||
|
||||
@ -1869,35 +1869,8 @@ function gr_draw_surface(series, x, y, z, clims)
|
||||
GR.surface(x, y, z, get(e_kwargs, :display_option, GR.OPTION_FILLED_MESH))
|
||||
elseif st === :mesh3d
|
||||
@warn "GR: mesh3d is experimental (no face colors)"
|
||||
conn = series[:connections]
|
||||
if typeof(conn) <: Tuple{Array, Array, Array}
|
||||
ci, cj, ck = conn
|
||||
if !(length(ci) == length(cj) == length(ck))
|
||||
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
|
||||
end
|
||||
else
|
||||
throw(ArgumentError("Argument connections has to be a tuple of three arrays."))
|
||||
end
|
||||
X = zeros(eltype(x), 4length(ci))
|
||||
Y = zeros(eltype(y), 4length(cj))
|
||||
Z = zeros(eltype(z), 4length(ck))
|
||||
@inbounds for I ∈ 1:length(ci)
|
||||
i = ci[I] + 1 # connections are 0-based
|
||||
j = cj[I] + 1
|
||||
k = ck[I] + 1
|
||||
m = 4(I - 1) + 1; n = m + 1; o = m + 2; p = m + 3
|
||||
X[m] = X[p] = x[i]
|
||||
Y[m] = Y[p] = y[i]
|
||||
Z[m] = Z[p] = z[i]
|
||||
X[n] = x[j]
|
||||
Y[n] = y[j]
|
||||
Z[n] = z[j]
|
||||
X[o] = x[k]
|
||||
Y[o] = y[k]
|
||||
Z[o] = z[k]
|
||||
end
|
||||
gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series), series)
|
||||
GR.polyline3d(X, Y, Z)
|
||||
GR.polyline3d(mesh3d_triangles(x, y, z, series[:connections])...)
|
||||
else
|
||||
throw(ArgumentError("Not handled !"))
|
||||
end
|
||||
|
||||
@ -1247,7 +1247,6 @@ _backend_skips = Dict(
|
||||
:gaston => [
|
||||
2, # animations
|
||||
31, # animations
|
||||
47, # TODO: support mesh3d
|
||||
49, # TODO: support polar
|
||||
50, # TODO: 1D data not supported for pm3d
|
||||
],
|
||||
|
||||
178
src/utils.jl
178
src/utils.jl
@ -1,6 +1,7 @@
|
||||
function treats_y_as_x(seriestype)
|
||||
return seriestype in (:vline, :vspan, :histogram, :barhist, :stephist, :scatterhist)
|
||||
end
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
treats_y_as_x(seriestype) = seriestype in (:vline, :vspan, :histogram, :barhist, :stephist, :scatterhist)
|
||||
|
||||
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
|
||||
n, m = size(z)
|
||||
colors = palette(vec(z))
|
||||
@ -143,7 +144,7 @@ allnan(istart::Int, iend::Int, args::Tuple) = all(anynan(args), istart:iend)
|
||||
|
||||
function Base.iterate(itr::NaNSegmentsIterator, nextidx::Int = itr.n1)
|
||||
i = findfirst(!anynan(itr.args), nextidx:itr.n2)
|
||||
i === nothing && return nothing
|
||||
i === nothing && return
|
||||
nextval = nextidx + i - 1
|
||||
|
||||
j = findfirst(anynan(itr.args), nextval:itr.n2)
|
||||
@ -191,7 +192,7 @@ makevec(v::AVec) = v
|
||||
makevec(v::T) where {T} = T[v]
|
||||
|
||||
"duplicate a single value, or pass the 2-tuple through"
|
||||
maketuple(x::Real) = (x,x)
|
||||
maketuple(x::Real) = (x, x)
|
||||
maketuple(x::Tuple{T,S}) where {T,S} = x
|
||||
|
||||
for i in 2:4
|
||||
@ -224,7 +225,7 @@ expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
|
||||
|
||||
# if the type exists in a list, replace the first occurence. otherwise add it to the end
|
||||
function addOrReplace(v::AbstractVector, t::DataType, args...; kw...)
|
||||
for (i,vi) in enumerate(v)
|
||||
for (i, vi) in enumerate(v)
|
||||
if isa(vi, t)
|
||||
v[i] = t(args...; kw...)
|
||||
return
|
||||
@ -254,7 +255,6 @@ end
|
||||
|
||||
createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end]
|
||||
|
||||
|
||||
sortedkeys(plotattributes::Dict) = sort(collect(keys(plotattributes)))
|
||||
|
||||
function _heatmap_edges(v::AVec, isedges::Bool = false, ispolar::Bool = false)
|
||||
@ -327,7 +327,6 @@ isscalar(::Any) = false
|
||||
|
||||
is_2tuple(v) = typeof(v) <: Tuple && length(v) == 2
|
||||
|
||||
|
||||
isvertical(plotattributes::AKW) = get(plotattributes, :orientation, :vertical) in (:vertical, :v, :vert)
|
||||
isvertical(series::Series) = isvertical(series.plotattributes)
|
||||
|
||||
@ -341,7 +340,6 @@ limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
|
||||
limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
|
||||
limsType(lims) = :invalid
|
||||
|
||||
|
||||
# recursively merge kw-dicts, e.g. for merging extra_kwargs / extra_plot_kwargs in plotly)
|
||||
recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...)
|
||||
# if values are not AbstractDicts, take the last definition (as does merge)
|
||||
@ -386,9 +384,7 @@ end
|
||||
handle_surface(z) = z
|
||||
handle_surface(z::Surface) = permutedims(z.surf)
|
||||
|
||||
function ok(x::Number, y::Number, z::Number = 0)
|
||||
isfinite(x) && isfinite(y) && isfinite(z)
|
||||
end
|
||||
ok(x::Number, y::Number, z::Number=0) = isfinite(x) && isfinite(y) && isfinite(z)
|
||||
ok(tup::Tuple) = ok(tup...)
|
||||
|
||||
# compute one side of a fill range from a ribbon
|
||||
@ -418,9 +414,7 @@ function concatenate_fillrange(x,y::Tuple)
|
||||
return xline, yline
|
||||
end
|
||||
|
||||
function get_sp_lims(sp::Subplot, letter::Symbol)
|
||||
axis_limits(sp, letter)
|
||||
end
|
||||
get_sp_lims(sp::Subplot, letter::Symbol) = axis_limits(sp, letter)
|
||||
|
||||
"""
|
||||
xlims([plt])
|
||||
@ -466,10 +460,7 @@ function contour_levels(series::Series, clims)
|
||||
levels
|
||||
end
|
||||
|
||||
|
||||
|
||||
for comp in (:line, :fill, :marker)
|
||||
|
||||
compcolor = string(comp, :color)
|
||||
get_compcolor = Symbol(:get_, compcolor)
|
||||
comp_z = string(comp, :_z)
|
||||
@ -478,7 +469,6 @@ for comp in (:line, :fill, :marker)
|
||||
get_compalpha = Symbol(:get_, compalpha)
|
||||
|
||||
@eval begin
|
||||
|
||||
function $get_compcolor(series, cmin::Real, cmax::Real, i::Int = 1)
|
||||
c = series[$Symbol($compcolor)]
|
||||
z = series[$Symbol($comp_z)]
|
||||
@ -489,7 +479,7 @@ for comp in (:line, :fill, :marker)
|
||||
end
|
||||
end
|
||||
|
||||
$get_compcolor(series, clims, i::Int = 1) = $get_compcolor(series, clims[1], clims[2], i)
|
||||
$get_compcolor(series, clims, i::Int=1) = $get_compcolor(series, clims[1], clims[2], i)
|
||||
|
||||
function $get_compcolor(series, i::Int = 1)
|
||||
if series[$Symbol($comp_z)] === nothing
|
||||
@ -499,7 +489,7 @@ for comp in (:line, :fill, :marker)
|
||||
end
|
||||
end
|
||||
|
||||
$get_compalpha(series, i::Int = 1) = _cycle(series[$Symbol($compalpha)], i)
|
||||
$get_compalpha(series, i::Int=1) = _cycle(series[$Symbol($compalpha)], i)
|
||||
end
|
||||
end
|
||||
|
||||
@ -518,33 +508,23 @@ function get_colorgradient(series::Series)
|
||||
end
|
||||
end
|
||||
|
||||
single_color(c, v = 0.5) = c
|
||||
single_color(grad::ColorGradient, v = 0.5) = grad[v]
|
||||
single_color(c, v=0.5) = c
|
||||
single_color(grad::ColorGradient, v=0.5) = grad[v]
|
||||
|
||||
get_gradient(c) = cgrad()
|
||||
get_gradient(cg::ColorGradient) = cg
|
||||
get_gradient(cp::ColorPalette) = cgrad(cp, categorical = true)
|
||||
get_gradient(cp::ColorPalette) = cgrad(cp, categorical=true)
|
||||
|
||||
function get_linewidth(series, i::Int = 1)
|
||||
_cycle(series[:linewidth], i)
|
||||
end
|
||||
get_linewidth(series, i::Int=1) = _cycle(series[:linewidth], i)
|
||||
get_linestyle(series, i::Int=1) = _cycle(series[:linestyle], i)
|
||||
|
||||
function get_linestyle(series, i::Int = 1)
|
||||
_cycle(series[:linestyle], i)
|
||||
end
|
||||
|
||||
function get_markerstrokecolor(series, i::Int = 1)
|
||||
function get_markerstrokecolor(series, i::Int=1)
|
||||
msc = series[:markerstrokecolor]
|
||||
isa(msc, ColorGradient) ? msc : _cycle(msc, i)
|
||||
end
|
||||
|
||||
function get_markerstrokealpha(series, i::Int = 1)
|
||||
_cycle(series[:markerstrokealpha], i)
|
||||
end
|
||||
|
||||
function get_markerstrokewidth(series, i::Int = 1)
|
||||
_cycle(series[:markerstrokewidth], i)
|
||||
end
|
||||
get_markerstrokealpha(series, i::Int=1) = _cycle(series[:markerstrokealpha], i)
|
||||
get_markerstrokewidth(series, i::Int=1) = _cycle(series[:markerstrokewidth], i)
|
||||
|
||||
const _segmenting_vector_attributes = (
|
||||
:seriescolor,
|
||||
@ -564,7 +544,7 @@ const _segmenting_vector_attributes = (
|
||||
:markershape,
|
||||
)
|
||||
|
||||
const _segmenting_array_attributes = (:line_z, :fill_z, :marker_z)
|
||||
const _segmenting_array_attributes = :line_z, :fill_z, :marker_z
|
||||
|
||||
function has_attribute_segments(series::Series)
|
||||
# we want to check if a series needs to be split into segments just because
|
||||
@ -589,19 +569,17 @@ function get_aspect_ratio(sp)
|
||||
return aspect_ratio
|
||||
end
|
||||
|
||||
get_size(series::Series) = get_size(series.plotattributes[:subplot])
|
||||
get_size(kw) = get(kw, :size, default(:size))
|
||||
get_size(plt::Plot) = get_size(plt.attr)
|
||||
get_size(sp::Subplot) = get_size(sp.plt)
|
||||
get_size(series::Series) = get_size(series.plotattributes[:subplot])
|
||||
|
||||
get_thickness_scaling(kw) = get(kw, :thickness_scaling, default(:thickness_scaling))
|
||||
get_thickness_scaling(plt::Plot) = get_thickness_scaling(plt.attr)
|
||||
get_thickness_scaling(sp::Subplot) = get_thickness_scaling(sp.plt)
|
||||
get_thickness_scaling(series::Series) =
|
||||
get_thickness_scaling(series.plotattributes[:subplot])
|
||||
get_thickness_scaling(series::Series) = get_thickness_scaling(series.plotattributes[:subplot])
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
makekw(; kw...) = KW(kw)
|
||||
|
||||
wraptuple(x::Tuple) = x
|
||||
@ -612,16 +590,18 @@ trueOrAllTrue(f::Function, x) = f(x)
|
||||
|
||||
allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg)
|
||||
allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg)
|
||||
allShapes(arg) = trueOrAllTrue(a -> is_marker_supported(get(_markerAliases, a, a)), arg) ||
|
||||
allShapes(arg) = (
|
||||
trueOrAllTrue(a -> is_marker_supported(get(_markerAliases, a, a)), arg) ||
|
||||
trueOrAllTrue(a -> isa(a, Shape), arg)
|
||||
allAlphas(arg) = trueOrAllTrue(a -> (typeof(a) <: Real && a > 0 && a < 1) ||
|
||||
(typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))), arg)
|
||||
)
|
||||
allAlphas(arg) = trueOrAllTrue(
|
||||
a -> (typeof(a) <: Real && a > 0 && a < 1) ||
|
||||
(typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))), arg
|
||||
)
|
||||
allReals(arg) = trueOrAllTrue(a -> typeof(a) <: Real, arg)
|
||||
allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg)
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
|
||||
"""
|
||||
Allows temporary setting of backend and defaults for Plots. Settings apply only for the `do` block. Example:
|
||||
@ -655,7 +635,6 @@ function with(f::Function, args...; kw...)
|
||||
oldbackend = CURRENT_BACKEND.sym
|
||||
|
||||
for arg in args
|
||||
|
||||
# change backend?
|
||||
if arg in backends()
|
||||
backend(arg)
|
||||
@ -716,10 +695,7 @@ mutable struct DebugMode
|
||||
end
|
||||
const _debugMode = DebugMode(false)
|
||||
|
||||
function debugplots(on = true)
|
||||
_debugMode.on = on
|
||||
end
|
||||
|
||||
debugplots(on=true) = _debugMode.on = on
|
||||
debugshow(io, x) = show(io, x)
|
||||
debugshow(io, x::AbstractArray) = print(io, summary(x))
|
||||
|
||||
@ -739,9 +715,7 @@ end
|
||||
DD(io::IO, plotattributes::AKW, prefix = "") = dumpdict(io, plotattributes, prefix, true)
|
||||
DD(plotattributes::AKW, prefix = "") = DD(stdout, plotattributes, prefix)
|
||||
|
||||
function dumpcallstack()
|
||||
error() # well... you wanted the stacktrace, didn't you?!?
|
||||
end
|
||||
dumpcallstack() = error() # well... you wanted the stacktrace, didn't you?!?
|
||||
|
||||
# -------------------------------------------------------
|
||||
# NOTE: backends should implement the following methods to get/set the x/y/z data objects
|
||||
@ -773,10 +747,9 @@ function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z}
|
||||
_series_updated(plt, series)
|
||||
end
|
||||
|
||||
function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z<:AbstractMatrix}
|
||||
setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z<:AbstractMatrix} = (
|
||||
setxyz!(plt, (xyz[1], xyz[2], Surface(xyz[3])), i)
|
||||
end
|
||||
|
||||
)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# indexing notation
|
||||
@ -837,9 +810,7 @@ function extend_to_length!(v::AbstractVector, n)
|
||||
extend_by_data!(v, vmax .+ (1:(n - length(v))))
|
||||
end
|
||||
extend_by_data!(v::AbstractVector, x) = isimmutable(v) ? vcat(v, x) : push!(v, x)
|
||||
function extend_by_data!(v::AbstractVector, x::AbstractVector)
|
||||
isimmutable(v) ? vcat(v, x) : append!(v, x)
|
||||
end
|
||||
extend_by_data!(v::AbstractVector, x::AbstractVector) = isimmutable(v) ? vcat(v, x) : append!(v, x)
|
||||
|
||||
# -------------------------------------------------------
|
||||
|
||||
@ -898,9 +869,7 @@ end
|
||||
|
||||
# push y[i] to the ith series
|
||||
# same x for each series
|
||||
function Base.push!(plt::Plot, x::Real, y::AVec)
|
||||
push!(plt, [x], y)
|
||||
end
|
||||
Base.push!(plt::Plot, x::Real, y::AVec) = push!(plt, [x], y)
|
||||
|
||||
# push (x[i], y[i]) to the ith series
|
||||
function Base.push!(plt::Plot, x::AVec, y::AVec)
|
||||
@ -923,12 +892,8 @@ function Base.push!(plt::Plot, x::AVec, y::AVec, z::AVec)
|
||||
plt
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
|
||||
# Some conversion functions
|
||||
# note: I borrowed these conversion constants from Compose.jl's Measure
|
||||
|
||||
@ -946,14 +911,17 @@ mm2px(mm::Real) = float(mm / MM_PER_PX)
|
||||
|
||||
|
||||
"Smallest x in plot"
|
||||
xmin(plt::Plot) = ignorenan_minimum([ignorenan_minimum(series.plotattributes[:x]) for series in plt.series_list])
|
||||
xmin(plt::Plot) = ignorenan_minimum(
|
||||
[ignorenan_minimum(series.plotattributes[:x]) for series in plt.series_list]
|
||||
)
|
||||
"Largest x in plot"
|
||||
xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.plotattributes[:x]) for series in plt.series_list])
|
||||
xmax(plt::Plot) = ignorenan_maximum(
|
||||
[ignorenan_maximum(series.plotattributes[:x]) for series in plt.series_list]
|
||||
)
|
||||
|
||||
"Extrema of x-values in plot"
|
||||
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# get fonts from objects:
|
||||
|
||||
@ -1139,40 +1107,70 @@ function shape_data(series, expansion_factor = 1)
|
||||
return x, y
|
||||
end
|
||||
|
||||
function construct_categorical_data(x::AbstractArray, axis::Axis)
|
||||
construct_categorical_data(x::AbstractArray, axis::Axis) = (
|
||||
map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x)
|
||||
end
|
||||
)
|
||||
|
||||
_fmt_paragraph(paragraph::AbstractString;kwargs...) = _fmt_paragraph(IOBuffer(),paragraph,0;kwargs...)
|
||||
_fmt_paragraph(paragraph::AbstractString;kwargs...) = _fmt_paragraph(
|
||||
IOBuffer(), paragraph, 0; kwargs...
|
||||
)
|
||||
|
||||
function _fmt_paragraph(io::IOBuffer,
|
||||
remaining_text::AbstractString,
|
||||
column_count::Integer;
|
||||
fillwidth=60,
|
||||
leadingspaces=0)
|
||||
|
||||
kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces)
|
||||
function _fmt_paragraph(
|
||||
io::IOBuffer, remaining_text::AbstractString, column_count::Integer;
|
||||
fillwidth=60, leadingspaces=0
|
||||
)
|
||||
kwargs = (fillwidth=fillwidth, leadingspaces=leadingspaces)
|
||||
|
||||
m = match(r"(.*?) (.*)",remaining_text)
|
||||
if isa(m,Nothing)
|
||||
if isa(m, Nothing)
|
||||
if column_count + length(remaining_text) ≤ fillwidth
|
||||
print(io,remaining_text)
|
||||
print(io, remaining_text)
|
||||
String(take!(io))
|
||||
else
|
||||
print(io,"\n"*" "^leadingspaces*remaining_text)
|
||||
print(io, "\n"*" "^leadingspaces*remaining_text)
|
||||
String(take!(io))
|
||||
end
|
||||
else
|
||||
if column_count + length(m[1]) ≤ fillwidth
|
||||
print(io,"$(m[1]) ")
|
||||
_fmt_paragraph(io,m[2],column_count + length(m[1]) + 1;kwargs...)
|
||||
_fmt_paragraph(io, m[2], column_count + length(m[1]) + 1; kwargs...)
|
||||
else
|
||||
print(io,"\n"*" "^leadingspaces*"$(m[1]) ")
|
||||
_fmt_paragraph(io,m[2],leadingspaces;kwargs...)
|
||||
_fmt_paragraph(io, m[2], leadingspaces; kwargs...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _document_argument(S::AbstractString)
|
||||
_fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S))
|
||||
_document_argument(S::AbstractString) = _fmt_paragraph(
|
||||
"`$S`: "*_arg_desc[Symbol(S)], leadingspaces=6+length(S)
|
||||
)
|
||||
|
||||
function mesh3d_triangles(x, y, z, cns)
|
||||
if typeof(cns) <: Tuple{Array, Array, Array}
|
||||
ci, cj, ck = cns
|
||||
if !(length(ci) == length(cj) == length(ck))
|
||||
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
|
||||
end
|
||||
else
|
||||
throw(ArgumentError("Argument connections has to be a tuple of three arrays."))
|
||||
end
|
||||
X = zeros(eltype(x), 4length(ci))
|
||||
Y = zeros(eltype(y), 4length(cj))
|
||||
Z = zeros(eltype(z), 4length(ck))
|
||||
@inbounds for I ∈ 1:length(ci)
|
||||
i = ci[I] + 1 # connections are 0-based
|
||||
j = cj[I] + 1
|
||||
k = ck[I] + 1
|
||||
m = 4(I - 1) + 1; n = m + 1; o = m + 2; p = m + 3
|
||||
X[m] = X[p] = x[i]
|
||||
Y[m] = Y[p] = y[i]
|
||||
Z[m] = Z[p] = z[i]
|
||||
X[n] = x[j]
|
||||
Y[n] = y[j]
|
||||
Z[n] = z[j]
|
||||
X[o] = x[k]
|
||||
Y[o] = y[k]
|
||||
Z[o] = z[k]
|
||||
end
|
||||
return X, Y, Z
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user