Attributes

Attributes map handles to mesh elements (e.g., to a vertex) to values (e.g., a vertex position). They are realized as a list of vectors of same size: if a new element is pushed, all vectors for this element grow simultaneously. Attributes can be disabled and enabled. Disabled attributes remain unchanged while enabled attributes grow.

Note that an efficient implementation of attribute lists may define a particular type for this list (as a named tuple). This requires that all attributes must be defined during initialization (i.e., there is no way to add attributes later). Disable attributes that are currently not required.

Indexing

Attributes are indexed by handles, tuples of handles, arrays of handles, or generators (that yield handles):

# Let ma be a managed attribute list and x one of its attributes.
# Let ma be index by handles of type H.

h = H(1)

x[h] == 0          # read single
x[h] = 1           # write single

                   #= read multiple

x[(h,h)]           # yields tuples (x[h], x[h])
x[[h,h]]           # yields array [x[h], x[h]]

sum(x[used(ma)])   # sums x for all handles generated by used(ma)
x[used(ma)]        # yields generator

                   #= write multiple

i = H(2)
x[(h, i)] = 1
x[(h, i)] = (1,2)
x[[h, i]] = [1,2]

x[used(ma)] = 1
x[used(ma)] = 1:n_used(ma)
PMeshAttributes.attrlengthMethod

Get number of entries in attributes. This is the length of [vec](@ref)(attr) for any enabled attribute attr in a.

Note

length(a) gives the number of attributes in a.

source
PMeshAttributes.cloneFunction
newattrs = clone(attrs::Attributes)

Create identical copy of attrs but don't copy data for disabled attributes.

source
PMeshAttributes.cloneMethod
anew = clone(a::Attribute)

Create identical copy (deepcopy of vector) of enabled attribute, don;t copy vector data for disabled attribute.

source
PMeshAttributes.createattributesFunction
a = createattributes(:name => spec, ... [; htyp=Int])
a = createattributes((:name => spec, ...) [; htyp=Int])

a = createattributes([:name => spec, ...], [; htyp=Int])
a = createattributes(Dict(:name => spec, ...), [; htyp=Int])

Create Attributes from list with common index/handle type htyp. The two calls create NamedTuples, the second two calls create Dicts.

The specification is given as a list (Tuple or Vector) or Pairs or 2-Tuples. The preferred notation is Pairs and :name => spec (instead of (:name, spec).

The specification spec for each attribute is either a single type (attribute is enabled with zero default values, see Attribute) or the result from specifyattr.

See also specifyattr, Attribute

source
PMeshAttributes.indicesMethod
is = indices(ma::ManagedAttributes[; i0 = I(1))

Integer range of all indices from Int(i0) to n_total

Note

indices returns a UnitRange, whereas handles generates handles (of type I) from integer indices.

See also handles

source
PMeshAttributes.initattr!Method
initattr!(ma, n[, use=true)

Create n elements with used state.

Precondition

Initializes empty ma: requires n_total(ma) == 0.

source
PMeshAttributes.nextwithMethod
j = nextwith(predicate, ma::ManagedAttributes[, i0])

Get next index from i0 that satisfies predicate(ma, i0). Returns invalid handle I(0) if no such handle exists.

Note

The index i0 is a handle (type), and the method returns a handle.

See also nextused

source
PMeshAttributes.setenabled!Function
setenabled!(attr[, state::Bool=true])
setenabled!(attrs, (:name, state::Bool); initialize=true)
setenabled!(attrs, dict::Dict{Symbol, Bool); initialize=true)

Set enabled state for attribute name or for all attributes name => state in dict. Fill with defaultvalue if initialize==true.

See also Attributes, isenabled, enabled

source
PMeshAttributes.AttributeType
# create an attribute with default value x0
a= createattribute(typ::Type{T}[, index::Type[; enabled=true, x0=zero(typ))

indextype(a)        # query index type
eltype(a)           # query element type T
isenabled(a)
vec(a)              # get raw Vector{T}
length(a)           # get length of vec(a)
sizehint!(a, n)     # same as sizehint!(vec(a))
a[h]                # access by index or handle
defaultvalue(a)     # query default value
setdefaultvalue!(a)

An attribute of a mesh.

Attributes are stored for vertices, faces, half-edges and edges of a mesh. Whenever the number of elements (vertices or factes or ...) changes, all associated attributes change in size. Attributes can disabled such that they will not resize until they are enabled again.

Typically, one operates on a Dict-like set of named Attributes'.

Each attribute is vector-valued and stores per-element values, which can be accessed by indices or handles: pass Hnd type as index.

See also Attributes

source

Mapping attribute values

Attribute values can be maped by functions, i.e., one can construct "virtual read-only" attributes. Such mapped attributes can be evaluated using the same indexing as for attributes.

# x is an attribute, f and g are functions

fx = map(f, x)
fx[h]          # is equivalent to f.(x[h])

fx = f ∘ x     # is equivalent to map(f, x)

gfx = g ∘ fx   # maps by g ∘ f
gfx[h]         # is equivalent to g.(f.(x[h])) == g.(fx(h))

gfx = fx ∘ g   # maps by f ∘ g
gfx[h]         # is equivalent to f.(g.(x[h])) == f.(gx(h))

Note that for any composition with (from left or from right), the attribute is always evaluated first, i.e., you compose the mapping.

Base.mapMethod

fa = map(f, attr) x = fa[idx]

Combine reading attr with a map f. Think of fa as a "read-only, virtual attribute".

Using map as above is equivalent to

x = f.(attr[idx])

Composition can be used as a syntactic alternative or for composing maps, e.g.,

fa = f ∘ attr
x = fa[idx]

gfa = g ∘ fa
y = gfa[idx]   # y == g.(f.(x)) == (g ∘ f).(x)

fga = fa ∘ g
y = fga[idx]   # y == f.(g.(x)) == (f ∘ g).(x)
source