Line data Source code
1 : """
2 : g = geometry(mesh, x)
3 : len = arclength(g, hs)
4 : len = arclength(g, es)
5 :
6 : Compute total length of (half-)edges. Use to compute arc-length of
7 : edge curves.
8 :
9 : !!! note
10 : This method does not check whether input is a 1-manifold
11 : connected curve (see [`ishalfedgecurve`](@ref)).
12 :
13 : See also [`edgelength`](@ref), [`ishalfedgecurve`](@ref),
14 : [`arclengthknots`](@ref)
15 : """
16 0 : function arclength(g::AbstractGeometry, edges)
17 0 : sum(edgelength(g, e) for e in edges)
18 : end
19 :
20 : """
21 : ishalfedgecurve(mesh, hs[; closed=false])
22 :
23 : Return `true` if `hs` is a sequence of connected half-edges in `mesh`.
24 : If `closed==true`, the first and the last half-edge *must* be
25 : connected.
26 :
27 : See also [`arclength`](@ref)
28 : """
29 0 : function ishalfedgecurve(mesh::Mesh, halfedges; closed::Bool=false)
30 0 : h0 = first(halfedges)
31 0 : hnext = h0
32 :
33 0 : for h::HHnd in halfedges
34 0 : (h == h0) && continue
35 0 : (destination(mesh, hnext) == source(mesh, h)) || return false
36 :
37 0 : hnext = h
38 0 : end
39 :
40 0 : closed && return (destination(mesh, hnext) == source(mesh, h0))
41 :
42 0 : true
43 : end
44 :
45 : """
46 : g = geometry(mesh, x)
47 : ts = arclengthknots(g, halfedges)
48 :
49 : Get knot values for each `i`-th [`destination`](@ref) vertex of
50 : `halfedges` such that `ts[i] == arclength(g, halfedges[1:i])` is
51 : a cumulative sum of [`arclength`](@ref)s.
52 :
53 : !!! note
54 : `ts` does **not** contain the knot value `0` associated with
55 : the [`source`](@ref) vertex of `first(halfedges)`!
56 :
57 : !!! note
58 : The knots may be used as input to [`positionhalfedgecurve!`](@ref).
59 :
60 : !!! note
61 : This method does not check whether input is a 1-manifold
62 : connected curve (see [`ishalfedgecurve`](@ref)).
63 :
64 : See also [`arclength`](@ref), [`uniformknots`](@ref),
65 : [`positionhalfedgecurve!`](@ref)
66 : """
67 0 : function arclengthknots(g::AbstractGeometry, halfedges)
68 0 : cumsum(edgelength(g, h) for h::HHnd in halfedges)
69 : end
70 :
71 0 : uniformknots(_::AbstractGeometry, halfedges) = uniformknots(halfedges)
72 0 : uniformknots(halfedges) = 1:length(halfedges)
73 :
74 : """
75 : ts = uniformknots(halfedges)
76 :
77 : g = geometry(mesh, x)
78 : ts = uniformknots(g, halfedges)
79 :
80 : Get uniformly spaced knot sequence similar to
81 : [`arclengthknots`](@ref).
82 :
83 : !!! note
84 : This method doesn't require the `mesh` [`geometry`](@ref)!
85 :
86 : !!! note
87 : `ts` does **not** contain the knot value `0` associated with
88 : the [`source`](@ref) vertex of `first(halfedges)`!
89 :
90 : !!! note
91 : The knots may be used as input to [`positionhalfedgecurve!`](@ref).
92 :
93 : See also [`arclengthknots`](@ref), [`positionhalfedgecurve!`](@ref)
94 : """ uniformknots
95 :
96 0 : function positionhalfedgecurve!(f::Function,
97 : g::AbstractGeometry, halfedges;
98 : knots = arclengthknots(g, halfedges))
99 0 : mesh = tessellation(g)
100 0 : x = position(g)
101 :
102 0 : for (i, h) in enumerate(halfedges)
103 0 : h::HHnd
104 0 : v = destination(mesh, h)
105 0 : x[v] = f(knots[i] / knots[end])
106 0 : end
107 :
108 0 : v0 = source(mesh, first(halfedges))
109 0 : x[v0] = f(zero(eltype(knots)))
110 :
111 0 : nothing
112 : end
113 :
114 0 : function positionhalfedgecurve!(f::Function,
115 : g::AbstractGeometry, halfedges,
116 : gref::AbstractGeometry)
117 0 : positionhalfedgecurve!(f, g, halfedges;
118 : knots = arclengthknots(gref, halfedges))
119 : end
120 :
121 : """
122 : g = geometry(mesh, x)
123 : positionhalfedgecurve!(f, g, halfedges
124 : [; knots=arclengthknots(g, halfedges)])
125 :
126 : positionhalfedgecurve!(f, g, halfedges;
127 : knots = uniformknots(halfedges))
128 :
129 : Set [`position`](@ref)s of vertices that span the curve specified by
130 : `halfedges` as `f(t)` where `t = knots[i] / knots[end] ∈ [0,1]`.
131 :
132 : !! note
133 : The method sets `x` ("output"). Note that `knots` may have to be be
134 : determined from a different attribute ("input").
135 :
136 : See example below with input `gx` and output `gu`.
137 :
138 : gx = geometry(mesh, x)
139 : gu = geometry(mesh, u)
140 :
141 : positionhalfedgecurve!(f, gu, halfedges;
142 : knots = arclengthknots(gx, halfedges))
143 :
144 : # short for using knots spaced by arc-length w.r.t gx
145 : positionhalfedgecurve!(f, gu, halfedges, gx)
146 :
147 : !!! warning "precondition"
148 : If `halfedges` specifies a closed curve, `f` must be *periodic*
149 : such that `f(0) == f(1)`.
150 :
151 : !!! note
152 : `knots` is defined as returned by, e.g., [`arclengthknots`](@ref),
153 : i.e., the first knot `t = 0` is given *implicitly* and *not* contained
154 : in `knots`.
155 :
156 : Example:
157 :
158 : circle(t) = (cos(2π*t), sin*(2π*t), zero(t))
159 :
160 : g = geometry(mesh, Val(:x))
161 : loop = first(findboundaryloops(mesh))
162 :
163 : positionhalfedgecurve!(circle, g, loop)
164 :
165 : !!! note
166 : This method does not check whether input is a 1-manifold
167 : connected curve (see [`ishalfedgecurve`](@ref)).
168 :
169 : See also [`arclengthknots`](@ref), [`uniformknots`](@ref)
170 : """ positionhalfedgecurve!
171 :
172 : # TODO: piecewise helper ("corners")
|