## Archive for February, 2014

### Copy text file without hard-wrap new lines

Friday, February 28th, 2014

I often format small text entries in vim and then copy them into other places like web forms. In vim I like to have a hard 80 character line wrap. But this means that after every 80 characters I have a newline character. If I just copy the file or from the terminal screen then I’ll impose this hard wrap in the submitted text. I’ve noticed that this is especially bad for academic review submissions because the submission system might then additionally impose its own hard wrap at a different width causing a very staggered, ragged appearance.

Here’s my solution to copy a text file without newlines but keeping double newlines which indicate paragraphs.

cat % | perl -pe '\$/=""; s/\n([^\n])/ \1/g;' | pbcopy


There must be a way to do this inside of vim properly, but I couldn’t figure it out.

### How does matlab’s popularity stack up in a PYPL google trends comparison?

Thursday, February 27th, 2014

Java still reins as the most popular programming language according to many metrics including PYPL. This compares [language] tutorial searching trends on google. Matlab sits comfortably at the level of Ruby, below Python but above the decling Perl.

### Libigl on github

Wednesday, February 26th, 2014

We’ve migrated libigl, our simple C++ library for geometry processing, to a public github repository. Hopefully this makes it a bit easier for others to use.

If you’re interested in trying libigl just head over to our github repo and clone a copy.

If you’re interested in helping the development of libigl, contact me and I can add your github username to our team.

Enjoy!

### Compute centroid of a polyhedron

Tuesday, February 18th, 2014

I ran into a concise algorithm for compute the centroid (center of mass) of an arbitrary closed 3D polyhedron. If you have a closed triangle mesh with vertices V and faces in F then here’s an implementation in matlab:

% Rename corners
A = V(F(:,1),:);
B = V(F(:,2),:);
C = V(F(:,3),:);
% Needs to be **unnormalized** normals
N = cross(B-A,C-A,2);
% total volume via divergence theorem: ∫ 1
vol = sum(sum(V(F(:,1),:).*N))/6;
% centroid via divergence theorem and midpoint quadrature: ∫ x
C = 1/(2*vol)*(1/24* sum(N.*((A+B).^2 + (B+C).^2 + (C+A).^2)));


### Spill-when-empty cup prototype

Friday, February 14th, 2014

Yesterday I got around to designing a prototype for an idea I’ve had for a long time. It’s a cup that tumps over if it’s empty but stands upright stably when full of liquid. I got a bit lucky with my design by eyeballing the center of mass and density balance between our 3D printer’s material and water. But it works!

### Open IEEE pdf without banner

Tuesday, February 11th, 2014

The IEEE Xplore library has a very annoying way of serving up PDFs. The page has two frames, one’s a small banner at the top and the bother is the PDF. Both Safari and Chrome keep the banner in focus so when I try to zoom I’m just zooming the banner. Here’s a javascript bookmarklet to open that second frame as a proper page:

javascript:(function(){window.location.href=document.getElementsByTagName("frame")[1].src;})()


### Blurring a semi-transparent image

Monday, February 10th, 2014

My brain paused a moment today trying to think how I can correctly blur an RGBA image (a color image with an alpha channel encoding transparency or rather opacity). Assuming you have an image in X and an alpha-map in A here’s a small matlab script demonstrating how to premultiply and then unpremultiply to get the correct output image Y and output alpha map B.

% blur kernel
H = fspecial('gaussian',100,100);
% pre-multiply
XA = bsxfun(@times,X,A);
% Apply blur to pre-multiplied image
XAH = imfilter(XA,H,'replicate');
% Apply blur to alpha mask
B = imfilter(A,H,'replicate');
% _Un_-pre-multiply by blurred mask (plus eps to avoid divide by zero
Y = bsxfun(@rdivide,XAH,B+(B==0)*eps);
% Checkerboard background function
checker = @(im,A) bsxfun(@times,1-A,repmat(1-0.2*xor((mod(repmat(0:size(im,2)-1,size(im,1),1),8*2)>7),(mod(repmat((0:size(im,1)-1)',1,size(im,2)),8*2)>7)),[1 1 3])) + bsxfun(@times,A,im);
% Show result
imshow([ ...
X repmat(A,[1 1 3]); ...
checker(X,A) XA; ...
XAH repmat(B,[1 1 3]); ...
Y checker(Y,B)])


### Photoshop-style checkboard background in MATLAB

Monday, February 10th, 2014

Here’s a gnarly one-liner to produce a checkerboard image ch with the same dimensions as you image im in matlab:

ch = repmat(1-0.2*xor((mod(repmat(0:size(im,2)-1,size(im,1),1),8*2)>7),(mod(repmat((0:size(im,1)-1)',1,size(im,2)),8*2)>7)),[1 1 3]);


This is useful for alpha-compositing. So suppose you had an alpha-map A to extract the star from this colorful image im. Then you could composite the star over ch:

imshow([ ...
ch; ...
repmat(A,[1 1 3]); ...
im; ...
bsxfun(@times,ch,1-A)+bsxfun(@times,im,A)])


Update: Here’s an even gnarlier anonymous function which takes an image im and an alpha map A and produces an image of the composite over the checkboard:

checker = @(im,A) bsxfun(@times,1-A,repmat(1-0.2xor((mod(repmat(0:size(im,2)-1,size(im,1),1),82)>7),(mod(repmat((0:size(im,1)-1)’,1,size(im,2)),8*2)>7)),[1 1 3])) + bsxfun(@times,A,im);

Then you can quickly display your checkboard background images with:

imshow(checker(im,A))


### Understanding OpenGL screen z (depth) values

Saturday, February 8th, 2014

I was trying to unproject a depth image into an OpenGL and was bit surprised to find that my choice of near and far plane values affected the influence of my “window Z” values used to unproject. This really shouldn’t have been a surprise when considering how the perspective matrix is formed. If you’re using gluPersepctive then your projection matrix P is:

P =  / x 0 0           0         \
|  0 y 0           0          |
|  0 0 (f+n)/(n-f) 2fn/(n-f)  |
\ 0 0 -1          0         /


where x and y control the field of view angle and aspect ratio, and f and n are the far and near clipping depths respectively.

The projection of a world point z = (0 0 z 1)T is then given by computing p = P * z then applying perspective division q = p / p.w. Despite the incorect documentation, gluProject then computes a window “depth” via winZ = (q.z+1)/2.

Following these formulae we can derive a relationship between winZ and the z-coordinate of our point on the z-axis. Namely,

winZ = (p.z/p.w+1)/2
p.z/p.w = 2*winZ-1
p.w = -z
p.z = z*(f+n)/(n-f) + 2fn/(n-f)
(z(f+n)/(n-f) + 2fn/(n-f))/(-z) = 2winZ-1
z = fn/(f*winZ-n*winZ-f)


or equivalently

winZ = f(n+z)/((f-n)z)


Notably, when z=-f then winZ = 1 and when z=-n then winZ = 0. In between, we have an inverse relationship:

### Graphics Interface proceedings online

Wednesday, February 5th, 2014

These took a while to dig up. Google scholar seems not to have found these yet and individual papers haven’t been extracted.