Archive for February, 2012

Isointerval contour plots on triangle meshes in Matlab

Wednesday, February 29th, 2012

Matlab let’s you plot contours of scalar functions defined on grid-surfaces. But this is not easily achieved if you’re working with a triangle mesh. I had previously attempted to achieve this by first resampling the function onto a grid surface and then using Matlab’s built-in contour. This eventually (very slowly) gives you nice contour intervals and isolines separating them, but it makes the boundary of the domain ugly and doesn’t easily extend to 3d surfaces.

But now I’ve found that using the right colormap and the right rendering flags you can get pretty close to that sort of contour plot without the slow resampling step. The trick seems to be using a relatively small colormap and setting the ‘FaceLighting’ flag to ‘phong’ and the ‘FaceColor’ flag to ‘interp’. If your mesh is in V and F and you have some scalar functions in the columns of W then you can render 10 isointervals of alternating green and yellow using:


t = trisurf(F,V(:,1),V(:,2),V(:,3),W(:,5),'EdgeColor','none','FaceColor','interp','FaceLighting','phong');
colormap(repmat([1.0 0.95 0;0.1 0.5 0.2],10/2,1));
light('Position',[-1.0,-1.0,100.0],'Style','infinite');
axis equal;
view(2);

ogre isointervals in matlab triangle mesh
Note: the light command is not necessary to achieve sharp isointervals. But the setting the face “lighting” to ‘phong’ is necessary

And with a little effort, you can achieve something close to isointervals separated by isolines:


% number of isointervals
nin = 8;
M = jet(nin);
% thickness ratio of each isointerval compared to "isoline"
thickness = 10;
MM = reshape(permute(cat(3,repmat(M,[1 1 thickness]),zeros([nin 3 1])),[3 1 2]),nin*thickness + nin,3);
colormap(MM)
colorbar

ogre isointervals and isolines in matlab triangle mesh
Or on a 2D mesh without the light call:
woody isointervals and isolines in matlab triangle mesh

Matlab face/edge alpha and phong lighting

Wednesday, February 29th, 2012

Turns out matlab’s figure renderers can’t handle transparency and phong lighting simultaneously. I noticed this when trying to have transparent edges overlaid on a phong shaded surface.
Matlab documentation reads:

You do not specify Phong lighting (OpenGL does not support Phong lighting; if you specify Phong lighting, MATLAB uses the ZBuffer renderer).

Or

Figure objects use transparency (OpenGL is the only MATLAB renderer that supports transparency).

So that’s that. Hopefully Matlab will fix this in the future. For now I will probably just composite figures in Photoshop if need be.

Resizing animated gifs scaling issue

Monday, February 27th, 2012

When trying to resize animated gifs into thumbnails using imagemagick’s convert, I noticed that with certain gifs the first frame of the animation would resize correctly but the subsequent frames would remain unscaled or only partially scaled. The command I was using was:


convert input.gif -thumbnail x200 -resize '200x<' -resize 50% -gravity center -crop 100x100+0+0 +repage output.gif

For non-animated gifs, this correctly makes a 100 by 100 thumbnail. For animated gifs where each frame is sufficiently different this creates a animated thumbnail. But for animations whose frames differ only slightly it seems to resize each "difference frame" which may not have the same bounding box. To correct this just add the command "-coalesce" to the beginning of the imagemagick command sequence. Like this:


convert input.gif -coalesce -thumbnail x200 -resize '200x<' -resize 50% -gravity center -crop 100x100+0+0 +repage output.gif

Patch for colormake to properly handle redirecting std err

Friday, February 10th, 2012

I started using colormake which is a great little perl script that wraps the make command, colorizing its output. I liked it so much that I quickly decided to make an alias in my bash .profile so that whenever I called make I would actually run colormake:


alias make=colormake

Note: The original colormake script is called cmake, but I renamed it to colormake to avoid conflict with the cmake.

This was going fine until I want to actually play with my typical make output. One thing I like to be able to do is redirect all of my errors to a file:


make 2>make.err

My alias to colormake broke this because the first thing the colormake wrapper does is redirect all of make’s std err output to std out.

Here’s my patch to the colormake (cmake) script that more properly deals with stderr. I also provide a fix to the errors from using stty incorrectly (though I actually don’t like the extra feature of colormake which trims commands to fit the window):


#!/bin/bash
#
# Wrapper around make to colorize its output.
#
# This patch fixes problems with calling stty in a script and redirecting std
# err
#

## use terminal size but avoid "stty: stdin isn't a terminal" warning from stty 
#STTY_SIZE=`stty size 2>/dev/null`
# Don't pass a terminal size (soft wrap entire commands)
STTY_SIZE=""

if [ -t 1 ];
then
  # Std out is tty
  if [ -t 2 ];
  then
    # Std err is tty
    make $* 2>&1 | colormake.pl $STTY_SIZE                                                              
    ret_val=${PIPESTATUS[0]}
  else
    # Std err is not tty
    # only pipe std out to colormake
    make $* | colormake.pl $STTY_SIZE                                                              
    ret_val=${PIPESTATUS[0]}
  fi
else
  # Std out is not tty
  make $*
  ret_val=$? 
fi                                                                                        
exit $ret_val

Update: Using PIPESTATUS I made sure that this script returns the return code of the make call.

Linking to eigen cross product requires including the right eigen header

Friday, February 3rd, 2012

We were foiled for a while today by a strange eigen error. We successfully compiled a function that called eigen’s cross product function. But then linking to our compiled function resulted in linker errors within the cross product function. Our errors looked like this


"Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >::cross_product_return_type<Eigen::Matrix<double, 1, 3, 1, 1, 3> >::type Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >::cross<Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&) const", referenced from:
      void igl::per_face_normals<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&)in libigl.a(per_face_normals.o)

The workaround to this bug in eigen is to be sure to include the following header in the function compiling with the cross product call:


#include <Eigen/Geometry>