octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

New plotting function surfl


From: Kai Habel
Subject: New plotting function surfl
Date: Sun, 09 Nov 2008 16:54:37 +0100
User-agent: Thunderbird 2.0.0.17 (X11/20080922)

Hello all,

the attached changeset adds the new plotting function surfl. To work
properly it requires the previous changeset about surface normals to be
applied as well.

The function surfl plots lighted surfaces. For best visual experience
colormaps like pink, copper, bone, or gray should be used.

For example:

colormap(bone);
surfl(peaks);
shading interp;

The function should work pretty well, so please give it try and report
bugs.

Kai
# HG changeset patch
# User Kai Habel
# Date 1226245327 -3600
# Node ID cacabddbb04affd8ea987eb6528813f8f47a4891
# Parent  36c59eb57b3764c762d273499c2730c47093ab04
Add new 3D plotting function surfl

diff -r 36c59eb57b37 -r cacabddbb04a scripts/ChangeLog
--- a/scripts/ChangeLog Sun Nov 09 15:58:24 2008 +0100
+++ b/scripts/ChangeLog Sun Nov 09 16:42:07 2008 +0100
@@ -1,3 +1,7 @@
+2008-11-09  Kai Habel <address@hidden>
+
+       * plot/surfl.m: New function file
+
 2008-09-28  Jaroslav Hajek <address@hidden>
 
        * optimization/__fdjac__.m: New function file.
diff -r 36c59eb57b37 -r cacabddbb04a scripts/plot/surfl.m
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/surfl.m      Sun Nov 09 16:42:07 2008 +0100
@@ -0,0 +1,192 @@
+## Copyright (C) 2008 Kai Habel
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} surfl (@var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {} surfl (@var{z})
+## @deftypefnx {Function File} {} surfl (@var{x}, @var{y}, @var{z}, @var{L})
+## @deftypefnx {Function File} {} surfl (@var{x}, @var{y}, @var{z}, @var{L}, 
@var{P})
+## @deftypefnx {Function File} {} surfl (...,"light")
+## Plot a lighted surface given matrices @var{x}, and @var{y} from 
@code{meshgrid} and
+## a matrix @var{z} corresponding to the @var{x} and @var{y} coordinates of
+## the mesh.  If @var{x} and @var{y} are vectors, then a typical vertex
+## is (@var{x}(j), @var{y}(i), @var{z}(i,j)).  Thus, columns of @var{z}
+## correspond to different @var{x} values and rows of @var{z} correspond
+## to different @var{y} values.
+##
+## The light direction can be specified using @var{L}. It can be
+## given as 2-element vector [azimuth, elevation] in degrees or as 3-element 
vector [lx, ly, lz].
+## The default value is 45° counter-clockwise (using the z-axis) from the 
current view.
+##
+## The material properties of the surface can specified using a 4-element 
vector
+## @var{P} = address@hidden @var{D} @var{SP} @var{exp}] which defaults to
+## @var{p} = [0.55 0.6 0.4 10]. 
+## @table @code
+## @item "AM" strength of ambient light
+## @item "D" strength of diffuse reflection
+## @item "SP" strength of specular reflection
+## @item "EXP" specular exponent
+## @end table
+## 
+## The default lighting mode "cdata", changes the cdata property to give the 
impression
+## of a lighted surface. Please note: the alternative "light" mode, which 
creates a light
+## object to iluminate the the surface is not implemented (yet).
+##
+## Example:
+##
+## @example
+## colormap(bone);
+## surfl(peaks);
+## shading interp;
+## @end example
+## @seealso{surf, surface}
+## @end deftypefn
+
+## Author: Kai Habel <address@hidden>
+
+function retval = surfl (varargin)
+
+  [h, varargin] = __plt_get_axis_arg__ ("surfl", varargin{:});
+
+  oldh = gca ();
+  unwind_protect
+    axes (h);
+    newplot ();
+
+    # check for lighting type
+    use_cdata = true;
+    if (ischar(varargin{end}))
+      lstr = varargin{end};
+      if strncmp(tolower(lstr), "light", 5)
+        warning("light method not supported (yet), using cdata method 
instead");
+        # this can be implemented when light objects are being
+        # supported.
+        use_cdata = false;
+      elseif strncmp(tolower(lstr), "cdata", 5)
+        use_cdata = true;
+      else
+        usage("unknown lighting method");
+      endif
+      varargin(end) = [];
+    endif
+
+    # check for reflection properties argument
+    # refl_prop = [ambient light,
+    #              diffuse reflection,
+    #              specular reflection,
+    #              specular shine] 
+    if ((length(varargin{end}) == 4) && isnumeric(varargin{end}))
+      refl_prop = varargin{end};
+      varargin(end) = [];
+    else
+      # default values
+      refl_prop = [0.55 0.6 0.4 10];
+    endif
+    refl_norm = 1 / sum(refl_prop(1:3));
+
+    # check for light vector (lv) argument
+    have_lv = false;
+    if (isnumeric(varargin{end}))
+      len = numel(varargin{end});
+      lastarg = varargin{end};
+      if (len == 3)
+        lv = lastarg;
+        varargin(end) = [];
+        have_lv = true;
+      elseif (len == 2)
+        [lx ly lz] = sph2cart(lastarg(1) * pi/180, lastarg(2) * pi/180, 1.0);
+        lv = [lx ly lz];
+        varargin(end) = [];
+        have_lv = true;
+      endif
+    endif
+    
+    tmp = surface (varargin{:});
+    if (! ishold ())
+      set (h, "view", [-37.5, 30],
+          "xgrid", "on", "ygrid", "on", "zgrid", "on", "clim", [0 1]);
+    endif
+
+    # get view vector (vv)
+    a = axis;
+    [az, el] = view;
+    [vx vy vz] = sph2cart((az-90.0) * pi/180.0, el * pi/180.0, 1.0);
+    vv = [vx vy vz];
+    vv = vv / norm(vv);
+
+    if (!have_lv)
+      # calculate light vector (lv) from view vector
+      phi = 45.0;
+      Phi = phi/180.0*pi;
+      R = [cos(Phi) -sin(Phi) 0;\
+           sin(Phi)  cos(Phi) 0;\
+           0         0        1];
+      lv = (R * vv.').';
+    endif
+
+    vn = get(tmp,"vertexnormals");
+    dar = get(h, "dataaspectratio");
+    vn(:,:,1) *= dar(1);
+    vn(:,:,2) *= dar(2);
+    vn(:,:,3) *= dar(3);
+ 
+    vn = vn ./ repmat(sqrt(sumsq(vn,3)),[1 1 3]);
+
+    # ambient term
+    [nr, nc] = size(get(tmp,'zdata'));
+    cdata = ones(nr,nc) * refl_prop(1);
+
+    # diffuse term
+    lmat = repmat(lv(:),[1 nr nc]);
+    lmat = shiftdim(lmat,1);
+    diffterm = dot (lmat, vn, 3);
+    diffterm(diffterm <= 0) = 0;
+    cdata += refl_prop(2) * diffterm;
+
+    # specular term
+    tmp_vec = (vv + lv) / norm(vv + lv);
+    tmp_mat = repmat(tmp_vec(:), [1 nr nc]);
+    tmp_mat = shiftdim(tmp_mat, 1);
+    specterm = dot(tmp_mat, vn, 3);
+    specterm(specterm <= 0) = 0;
+    specterm = specterm .^ refl_prop(4);
+    cdata += refl_prop(3) * specterm;
+
+    set(tmp, "cdata", cdata .* refl_norm);
+    
+  unwind_protect_cleanup
+    axes (oldh);
+  end_unwind_protect
+
+  if (nargout > 0)
+    retval = tmp;
+  endif
+
+endfunction
+
+%!demo
+%! [X,Y,Z]=sombrero;
+%! colormap(copper);
+%! surfl(X,Y,Z);
+
+%!demo
+%! [X,Y,Z]=sombrero;
+%! colormap(copper);
+%! [az, el] = view;
+%! surfl(X,Y,Z,[az+225,el],[0.2 0.6 0.4 25]);
+

reply via email to

[Prev in Thread] Current Thread [Next in Thread]