Mercurial > repos > public > sbplib
changeset 109:142974097efc
Merged in feature/arclen-param (pull request #1)
Feature/arclen param
author | Martin Almquist <martin.almquist@it.uu.se> |
---|---|
date | Tue, 08 Dec 2015 10:42:20 +0100 |
parents | 9933169d2651 (current diff) 35d8b4c60dbc (diff) |
children | f5ed7ff58115 |
files | |
diffstat | 1 files changed, 93 insertions(+), 52 deletions(-) [+] |
line wrap: on
line diff
diff -r 9933169d2651 -r 142974097efc +grid/Curve.m --- a/+grid/Curve.m Fri Dec 04 16:46:32 2015 +0100 +++ b/+grid/Curve.m Tue Dec 08 10:42:20 2015 +0100 @@ -4,16 +4,17 @@ gp transformation end + methods %TODO: - % Errors or FD if there is no derivative function added. - % Concatenation of curves % Subsections of curves - % Stretching of curve paramter + % Stretching of curve parameter - done for arc length. % Curve to cell array of linesegments - % Should accept derivative of curve. + % Returns a curve object. + % g -- curve parametrization for parameter between 0 and 1 + % gp -- parametrization of curve derivative function obj = Curve(g,gp,transformation) default_arg('gp',[]); default_arg('transformation',[]); @@ -29,68 +30,24 @@ obj.g = g; obj.gp = gp; obj.transformation = transformation; - end - % Made up length calculation!! Science this before actual use!! - % Calculates the length of the curve. Makes sure the longet segment used is shorter than h_max. - function [L,t] = curve_length(C,h_max) - default_arg('h_max',0.001); - g = C.g; - h = 0.1; - m = 1/h+1; - t = linspace(0,1,m); - - [p,d] = get_d(t,g); - - while any(d>h_max) - I = find(d>h_max); - - % plot(p(1,:),p(2,:),'.') - % waitforbuttonpress - - new_t = []; - for i = I - new_t(end +1) = (t(i)+t(i+1))/2; - end - t = [t new_t]; - t = sort(t); - - [p,d] = get_d(t,g); - end - - L = sum(d); - - function [p,d] = get_d(t,g) - n = length(t); - - p = zeros(2,n); - for i = 1:n - p(:,i) = g(t(i)); - end - - d = zeros(1,n-1); - for i = 1:n-1 - d(i) = norm(p(:,i) - p(:,i+1)); - end - end end function n = normal(obj,t) + assert(~isempty(obj.gp),'Curve has no derivative!'); deriv = obj.gp(t); normalization = sqrt(sum(deriv.^2,1)); n = [-deriv(2,:)./normalization; deriv(1,:)./normalization]; end - % Plots a curve g(t) for 0<t<1, using n points. Retruns a handle h to the plotted curve. + % Plots a curve g(t) for 0<t<1, using n points. Returns a handle h to the plotted curve. % h = plot_curve(g,n) function h = plot(obj,n) default_arg('n',100); t = linspace(0,1,n); - p = obj.g(t); - h = line(p(1,:),p(2,:)); end @@ -125,6 +82,33 @@ end % Shows curve with name and arrow for direction. + % Length of arc from parameter t0 to t1 (which may be vectors). + % Computed using derivative. + function L = arcLength(obj,t0,t1) + assert(~isempty(obj.gp),'Curve has no derivative!'); + speed = @(t) sqrt(sum(obj.gp(t).^2,1)); + L = integral_vec(speed,t0,t1); + end + + % Creates the arc length parameterization of a curve. + % N -- number of points used to approximate the arclength function + function curve = arcLengthParametrization(obj,N) + default_arg('N',100); + assert(~isempty(obj.gp),'Curve has no derivative!'); + + % Construct arcLength function using splines + tvec = linspace(0,1,N); + arcVec = obj.arcLength(0,tvec); + tFunc = spline(arcVec,tvec); % t as a function of arcLength + L = obj.arcLength(0,1); + arcPar = @(s) tFunc(s*L); + + % New function and derivative + g_new = @(t)obj.g(arcPar(t)); + gp_new = @(t) normalize(obj.gp(arcPar(t))); + curve = grid.Curve(g_new,gp_new); + + end % how to make it work for methods without returns function p = subsref(obj,S) @@ -143,8 +127,6 @@ end - - %% TRANSFORMATION OF A CURVE function D = reverse(C) % g = C.g; @@ -265,6 +247,19 @@ end methods (Static) + + % Computes the derivative of g: R -> R^2 using an operator D1 + function gp_out = numericalDerivative(g,D1) + m = length(D1); + t = linspace(0,1,m); + gVec = g(t)'; + gpVec = (D1*gVec)'; + + gp1_fun = spline(t,gpVec(1,:)); + gp2_fun = spline(t,gpVec(2,:)); + gp_out = @(t) [gp1_fun(t);gp2_fun(t)]; + end + function obj = line(p1, p2) function v = g_fun(t) @@ -345,3 +340,49 @@ end end + + + +function g_norm = normalize(g0) + g1 = g0(1,:); + g2 = g0(2,:); + normalization = sqrt(sum(g0.^2,1)); + g_norm = [g1./normalization; g2./normalization]; +end + +function I = integral_vec(f,a,b) +% Wrapper around the built-in function integral that +% handles multiple limits. + + Na = length(a); + Nb = length(b); + assert(Na == 1 || Nb == 1 || Na==Nb,... + 'a and b must have same length, unless one is a scalar.'); + + if(Na>Nb); + I = zeros(size(a)); + for i = 1:Na + I(i) = integral(f,a(i),b); + end + elseif(Nb>Na) + I = zeros(size(b)); + for i = 1:Nb + I(i) = integral(f,a,b(i)); + end + else + I = zeros(size(b)); + for i = 1:Nb + I(i) = integral(f,a(i),b(i)); + end + end +end + +% Returns a function handle to the spline. +function f = spline(tval,fval,spline_order) + default_arg('spline_order',4); + [m,~] = size(tval); + assert(m==1,'Need row vectors.'); + + f_spline = spapi( optknt(tval,spline_order), tval, fval ); + f = @(t) fnval(f_spline,t); +end