Create a low resolution pdf of a LaTeX paper

April 21st, 2016

Here’re the steps I use to create a low resolution version of a pdf created by LaTeX.

The simple thing to do is to follow the steps to create a camera ready (high res) pdf but replace the JPG settings to downsample the images and perhaps reduce the quality.

If you have a lot of raster images, this will work OK.

However, if you have a lot of vector graphics images or just a lot of images, this will not truly bring down the size of the final pdf.

For this I make sure that all of my \includegraphics commands in LaTeX are of the form:

\includegraphics[width=\linewidth]{\figs/figure-file-name}

Notice three things:

  1. the width is explicitly specified,
  2. the figure directory is a command/macro \figs, and
  3. the filename does not have an extension (figure-file-name instead of figure-file-name.pdf)

Then at the beginning of my file I have defined \figs. For the normal high resolution pdf I use:

\newcommand{\figs}{}
\def\figs/{figs/}

When I switch to low resolution I use

\newcommand{\figs}{}
%\def\figs/{figs/}
\def\figs/{figs/low-res/}

And before compiling I run the commands:

mkdir -p figs/low-res/
mogrify -colorspace RGB -resize 400x -background white -alpha remove -quality 100 -format jpg -path figs/low-res/ figs/*.{pdf,png}[0]

There are a couple import flags here to ensure that the background is white and only a single output is created for pdfs with accidentally multiple art-boards/pages.

Mesh Arrangements for Solid Geometry preprint

April 21st, 2016

mesh booleans

I’m very excited to publish my work with Qingnan Zhou, Eitan Grinspun and Denis Zorin on mesh booleans at this year’s SIGGRAPH. The paper is titled Mesh Arrangements for Solid Geometry. The code is (and has been) in libigl and gptoolbox and pymesh.

Variadic mesh boolean operations in libigl and gptoolbox

April 14th, 2016

I’ve just pushed some new changes to libigl and gptoolbox to expose the variadic implementation of our robust mesh boolean operations. By variadic, I mean that the boolean function can take one mesh as input or two meshes as input (usual binary case) or three or four and so on. This means you can easily take the union or intersection of n objects, but it also means that complex operations can be reduced to single call. For example, identifying regions inside at least k out of n objects. I first became aware of this variadic concept when reading “QuickCSG: Arbitrary and Faster Boolean Combinations of N Solids”.

In libigl, you can call igl::copyleft::cgal::mesh_boolean with an n-long list of mesh vertex arrays and an n-long list of mesh face arrays. Rather than the usual union, intersection, minus etc., you can also pass a C++ function handle. This function handle will filter the winding number vector at any point in space. For example, if you’d like to extract the region inside object 0 and not inside object 1 and either inside object 2 or not inside object 3. The filter would return w(0) > 0 && w(1)<=0 && (w(2)>0 || w(3)<= 0).

After a bit of pointer tweaking, I’ve also exposed this interface to the matlab wrapper in gptoolbox. You can pass a matlab function handle after the optional argument ‘WindingNumberFilter’. For example, assuming V and F are cell arrays containing vertex position arrays and face indices respectively, the following command will extract the region inside at least 3 of the inputs:

 [VV,FF,J] = mesh_boolean(V,F,'','WindingNumberFilter',@(w) sum(w>0)>=3);

You could also call it with

 [VV,FF,J] = mesh_boolean(V{1},F{1},V{2},F{2},V{3},F{3},V{4},F{4},'','WindingNumberFilter',@(w) sum(w>0)>=3);

Here’s an example of extracting min-k results from 4 spheres:

four spheres variadic boolean operation

Since extraction from our mesh arrangement is cheap, each operation takes the same amount of time. And fortunately it seems that the mex function handle overhead is not so bad.

Update: Variadic operations are also useful for condensing entire binary CSG trees: (A union B) minus (C union D) could be a single extraction function on (A,B,C,D) return (w(0)>0 || w(1)>0) && !(w(2)>0 || w(3)>0)

Project page for “Computational Design of Reconfigurables”

April 13th, 2016

I’m excited to post the project page for an upcoming siggraph 2016 paper, “Computational Design of Reconfigurables” a collaboration with Akash Garg and Eitan Grinspun.

reconfigurables.

Video:

Abstract: A reconfigurable is an object or collection of objects whose transformation between various states defines its functionality or aesthetic appeal. For example, consider a mechanical assembly composed of interlocking pieces, a transforming folding bicycle, or a space-saving arrangement of apartment furniture. Unlike traditional computer-aided design of static objects, specialized tools are required to address problems unique to the computational design and revision of objects undergoing rigid transformations. Collisions and interpenetrations as objects transition from one configuration to another prevent the physical realization of a design. We present a software environment intended to support fluid interactive design of reconfigurables, featuring tools that identify, visualize, monitor and resolve infeasible configurations. We demonstrate the versatility of the environment on a number of examples spanning mechanical systems, urban dwelling, and interlocking puzzles, some of which we then realize via additive manufacturing.

Spatial-temporal information about collisions between objects is presented to the designer according to a cascading order of precedence. A designer may quickly determine when, and then where, and then how objects are colliding. This precedence guides the design and implementation of our four-dimensional spacetime bounding volume hierarchy for interactive-rate collision detection. On screen, the designer experiences a suite of interactive visualization and monitoring tools during editing: timeline notifications of new collisions, picture-in-picture windows for tracking collisions and suggestive hints for contact resolution. Contacts too tedious to remove manually can be eliminated automatically via our proposed constrained numerical optimization and swept-volume carving.

Parse floating point numbers from a string in ruby

April 11th, 2016

Given a string like "v 1.2 4.2342 8.2 -1.0e14" (e.g., from a .obj file), you could use the following ruby line to extract an ordered list of the contained floating point numbers:

line.scan(/[+-]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?/).collect{|s| s.to_f}

which would produce

=> [1.2, 4.2342, 8.2, 100000000000000.0]

Missing faces when importing into SketchUp

April 4th, 2016

When loading a mesh into sketchup, I noticed that sometimes faces would be missing:

cheburashka imported into sketchup with missing faces

two mesh file format IO implementations later, I realized the problem is not the file format but rather that sketch up seems to be ignoring faces (and sometimes edges?) smaller than a certain scale. For example if I scale the model down by 0.1 I see:

smaller cheburashka imported into sketchup with missing more faces

And if I scale the model up, eventually I get all of the faces:

larger cheburashka imported into sketchup with no missing faces

Still not sure how to ensure that all faces get loaded at the correct scale, but at least I know what the problem is now.

Using meshfix “from libigl”

March 30th, 2016

Here’s a little example of how to call meshfix using plain Eigen types to represent a mesh (i.e. in the libigl style. I’ve included this example in my github fork of the meshfix code.

#define MESHFIX_WITH_EIGEN
#include "meshfix.h"

#include <igl/read_triangle_mesh.h>
#include <igl/write_triangle_mesh.h>
#include <iostream>

int main(int argc, char * argv[])
{
  // Load in libigl's (V,F) format
  Eigen::MatrixXd V,W;
  Eigen::MatrixXi F,G;
  if(argc <= 2)
  {
    std::cout<<R"(Usage:
    ./meshfix-libigl [input](.obj|.ply|.stl|.off) [output](.obj|.ply|.stl|.off)
)";
    return EXIT_FAILURE;
  }
  igl::read_triangle_mesh(argv[1],V,F);
  meshfix(V,F,W,G);
  // Write to OBJ
  igl::write_triangle_mesh(argv[2],W,G);
}

Then you can run this by issuing something like:

./meshfix-libigl input.obj output.ply

March 30th, 2016

skinning course at SGP 2016

I’ll be teaching our Skinning course again this year. This time at the IGS 2016 summer school (host of the Symposium of Geometry Processing). The rest of the summer school (aka workshop) line-up is an all-star cast. Look forward to seeing you there.

Simple “parallel for” using C++11 std::thread

February 25th, 2016

It seems like Apple’s built-in clang will never support OpenMP. I really used OpenMP only for its #omp parallel for. Now that C++11 has support for multi-threading, I tried to write a very basic parallel for without OpenMP.

#include <vector>
#include <thread>
#include <iostream>

int main(int argc, char *argv[])
{
  const size_t nloop = 11;

  // Serial version
  {
    // Pre loop
    std::cout<<"serial:"<<std::endl;
    // loop over all items
    for(int i = 0;i<nloop;i++)
    {
      // inner loop
      {
        const int j = i*i;
        std::cout<<j<<std::endl;
      }
    }
    // Post loop
    std::cout<<std::endl;
  }

  // Parallel version
  // number of threads
  const size_t nthreads = std::thread::hardware_concurrency();
  {
    // Pre loop
    std::cout<<"parallel ("<<nthreads<<" threads):"<<std::endl;
    std::vector<std::thread> threads(nthreads);
    std::mutex critical;
    for(int t = 0;t<nthreads;t++)
    {
      threads[t] = std::thread(std::bind(
        [&](const int bi, const int ei, const int t)
        {
          // loop over all items
          for(int i = bi;i<ei;i++)
          {
            // inner loop
            {
              const int j = i*i;
              // (optional) make output critical
              std::lock_guard<std::mutex> lock(critical);
              std::cout<<i<<std::endl;
            }
          }
        },t*nloop/nthreads,(t+1)==nthreads?nloop:(t+1)*nloop/nthreads,t));
    }
    std::for_each(threads.begin(),threads.end(),[](std::thread& x){x.join();});
    // Post loop
    std::cout<<std::endl;
  }
}

It’s not as simple as slapping down #omp parallel for but it’s really just a few lines above and below the for loop. It can even determine the number of cores available and handle simple atomic operations.

Repeat each row of matlab matrix

February 16th, 2016

I swear I’ve posted this before, but here’s how to turn:

X = [11 12 13; ...
     21 22 23];

Into:

Y = [
  11 12 13; ...
  11 12 13; ...
  11 12 13; ...
  11 12 13; ...
  21 22 23; ...
  21 22 23; ...
  21 22 23; ...
  21 22 23];

That is, repeat each row, but maintain the order

Y = reshape(permute(repmat(X,[1 1 num_reps]),[3 1 2]),[],size(X,2));