Latest Posts from Saurabh Garg


Dense Connective Tissue section Amscope 50PC Prepared Slides

Dense connective tissue (section) is the 8th slide in the Amscope 50PC prepared slides. Dense connective tissue have densely packed fibers made up of mainly collagen (while lines in the micrograph below). The fibers in these tissues are regularly arranged and they are very strong but inelastic. Due to their in-elasticity, they can break if a strong force is applied across the fibers. Dense connective tissues forms the ligaments (connects muscles to bones) and tendons (connects bones to bones) in our body.

Micrographs [19 July 2015]
Amscope 50PC Prepared Slides

This post lists all the micrographs I have done from the Amscope 50PC prepared slides.


Dandelion Fuzz w.m. – Amscope 50PC Prepared Slides

Dandelion Fuzz whole mount (w.m.) is the 7th slide in the Amscope 50PC prepared slides. Dandelion is a yellow colored flower native to Eurasia and North America [Wikipedia]. What appears to be a single dandelion flower is actually made up of a large number of small flowers called florets! After removing the yellow petals from all florets, we are left with dandelion fuzz also known as seed head. The micrographs below show a single seed from the seed head.

Micrographs [19 July 2015]
Amscope 50PC Prepared Slides

This post lists all the micrographs I have done from the Amscope 50PC prepared slides.


A man gets an immense satisfaction from the knowledge of having done good work

You increase your self-respect when you feel you’ve done everything you ought to have done, and if there is nothing else to enjoy, there remains that chief of pleasures, the feeling of being pleased with oneself. A man gets an immense amount of satisfaction from the knowledge of having done good work and of having made the best use of his day, and when I am in this state I find that I thoroughly enjoy my rest and even the mildest forms of recreation.

Journal of Eugene Delacroix

Cross-platform high-resolution timer

Often there is a need to estimate the time it takes for a piece of code to run. This is useful not only for debugging but also for reporting the execution time of lengthy tasks to the user.

On Windows, QueryPerformanceFrequency() and QueryPerformanceCounter() can be used to determine the execution time of a code. QueryPerformanceFrequency() returns the frequency of the current performance counter in counts per second and QueryPerformanceCounter() returns a high resolution (<1µs) time stamp. Together they can be used to determine time it takes to run a piece of code is:

LARGE_INTEGER _frequency;
QueryPerformanceFrequency(&_frequency);

LARGE_INTEGER _start;
QueryPerformanceCounter(&_start);

// Code which takes a long time to run.

LARGE_INTEGER _stop;
QueryPerformanceCounter(&_stop);

double _intervalInSeconds = (_stop.QuadPart - _start.QuadPart) / _frequency.QuadPart;

On Linux, clock_gettime can be used to get a time interval with a resolution of nano-seconds. clock_gettime() requires two arguments: clockid_t and timespec structure. To build a timer, CLOCK_MONOTONIC is a good choice for clockid_t as the time is guaranteed to be monotonically increasing. timespec structure have two field: tv_sec (time in seconds) and tv_nsec (time in nanoseconds). Code to determine the time it takes to run a piece of code is:

struct timespec _start;
clock_gettime(CLOCK_MONOTONIC, &_start);

// Code which takes long time to run.

struct timespec _stop;
clock_gettime(CLOCK_MONOTONIC, &_stop);

double _intervalInseconds = (_stop.tv_sec + _stop.tv_nsec*1e-9) - (_start.tv_sec + _start.tv_nsec*1e-9);

I have written a simple class which can be user on both windows and Linux. It has the following interface:

class Timer
{
public:

    enum TimeUnit
    {
        TimeInSeconds = 1,
        TimeInMilliSeconds = 1000,
        TimeInMicroSeconds = 1000000
    };

public:

    Timer();
    ~Timer();

    // On Windows, returns true if high performance timer is available.
    // On Linux, always returns true.
    bool IsTimerAvailable();

    // Start the timer.
    void Start();

    // Stop the timer and return the time elapsed since the timer was started.
    double Stop(TimeUnit timeUnit = TimeInMilliSeconds);

    // Get the time elapsed since Start() was called.
    double TimeElapsedSinceStart(TimeUnit timeUnit = TimeInMilliSeconds);

    // Get the total time elapsed between Start() and Stop().
    double TotalTimeElasped(TimeUnit timeUnit = TimeInMilliSeconds);
};

You can download the code from the following links:
Timer.h
Timer.cpp
Timer_Unix.cpp
Timer.zip


Cucurbita Stem l.s. – Amscope 50PC Prepared Slides

Cucurbita stem lateral section (l.s.) is the 6th slide in the Amscope 50PC prepared slides. Cucurbita (Latin for gourd) is popularly known as squash, pumpkin, or gourd depending on species, variety, and local parlance.

Micrographs [24 May 2015]
Amscope 50PC Prepared Slides

This post lists all the micrographs I have done from the Amscope 50PC prepared slides.


SLogLib: An easy to use, fully customizable and extensible, cross-platform logging library

A long time ago when I was doing PhD I was implementing a very complex geometric algorithm for computing intersection of two triangular meshes. There were bugs in code which would trigger only in certain edge cases. Since it was a GUI program using std::cout was not an option. Initially I tried writing messages to a file but soon realized it was too tedious as code was spanned across several files and I had to manually insert file names, function names, line numbers for every logging message.

A quick search on Internet revealed many logging libraries. I tried couple of them (unfortunately I can’t remember their names now) but none of them allowed customization of the output. The libraries I came across could output to variety of devices, supported multi-threading and many other fancy features but it was not possible to change the way messages was reported to the user. This was very important to me because I wanted to format my messages in a particular way so that I can easily check how my code was crashing on edge cases.

So, I wrote the first version of SLogLib sometime in 2005. It was build on a single principle that user should be in complete control of how messages are written to devices. In order to do that, SLogLib wraps all information required for logging into a structure called Message and passes it to a Formatter. The Formatter converts the Message structure to a std::string which will be outputted to the device. The Formatter must be written by the user. However, to make it easier to start using SLogLib and illustrate how to write a Formatter few Formatters are included with SLogLib.

Over past decade SLogLib has been very useful to me for a variety of projects and I hope that other can find it useful as well. SLogLib is hosted on Github under MIT license. You can clone of fork it from here: https://github.com/saurabhg17/SLogLib.




Paramecium under Microscope in Pond Water

Paramecium in a sample of water taken from swan lake in Singapore Botanical Gardens.


Computing area of all facets in CGAL::Polyhedron_3

In this post I will show how to compute area of a facet in CGAL::Polyhedron_3.

ComputeFacetArea() Functor

ComputeFacetArea() is a thread-safe functor for computing the area of a given facet in a CGAL::Polyhedron_3. The facet must be a planar polygon with arbitrary number of sides. We need facet’s normal vector to compute it’s area. The facet normals must be be initialized using the ComputeFacetArea()’s constructor. The code for computing the facet normals is presented in this post: Computing normal of all facets in CGAL::Polyhedron_3.

#ifndef _SMESHLIB_OPERATIONS_COMPUTEFACETAREA_H_
#define _SMESHLIB_OPERATIONS_COMPUTEFACETAREA_H_

#include "PropertyMap.h"

namespace SMeshLib   {
namespace Operations {
;

// The ComputeFacetArea is a functor (delegate) to compute the area of a facet in CGAL::Polyhdeon_3.
// operator() is thread-safe.
// TPolyhedron is a type of CGAL::Polyhdeon_3.
// TFacetNormals is a property map associating a normal vector for each facet in the CGAL::Polyhdeon_3.
template<class TPolyhedron, class TFacetNormals>
struct ComputeFacetArea
{
public:
	
	// Redefine types from TPolyhedron for convenience.
	typedef typename TPolyhedron::Facet                                  Facet;
	typedef typename TPolyhedron::Traits::Vector_3                       Vector3;
	typedef typename TPolyhedron::Halfedge_around_facet_const_circulator HalfEdgeConstCirculator;
	
	// Return type of operator() required by QtConcurrent.
	typedef double result_type;
	
public:
	
	ComputeFacetArea(const TFacetNormals& facetNormals_)
		: facetNormals(facetNormals_)
	{}
	
	// Compute the area of a given facet.
	// The formula for computing facet area, which in general is a planar polygon, is from
	// http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm
	inline double operator() (const Facet& f) const
	{
		std::vector<Vector3> _vectors;
		HalfEdgeConstCirculator s = f.facet_begin();
		HalfEdgeConstCirculator e = s;
		CGAL_For_all(s, e)
		{
			_vectors.push_back(s->vertex()->point() - CGAL::ORIGIN);
		}
		
		Vector3 _sumCrossProducts(CGAL::NULL_VECTOR);
		const size_t N = _vectors.size();
		for(size_t i=0 ; i<N ; ++i)
		{
			_sumCrossProducts = _sumCrossProducts + CGAL::cross_product(_vectors[i], _vectors[(i+1)%N]);
		}
		
		return fabs((facetNormals.value(&f) * _sumCrossProducts) / 2.0);
	}
	
public:
	
	// Facet normals are required for computing the area of a facet.
	const TFacetNormals& facetNormals;
};

};	// End namespace Operations.
};	// End namespace SMeshLib.

#endif // _SMESHLIB_OPERATIONS_COMPUTEFACETAREA_H_
Using ComputeFacetArea() Functor

Area of a facet f can be computed as double area = ComputeFacetArea(h);.

For most purposes, it is better to compute area of all facets once and cache them for later use. It is best to store the results in an associative container which associates the facet handle with the area. In the following example, I use PropertyMap which is a wrapper for std::set.

#include "ImportOBJ.h"
#include "ComputeFacetArea.h"
#include "ComputeFacetNormal.h"
#include "PropertyMap.h"
#include "CGAL/Simple_cartesian.h"
#include "CGAL/Polyhedron_items_3.h"
#include "CGAL/HalfedgeDS_list.h"
#include "CGAL/Polyhedron_3.h"

typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Polyhedron_3<Kernel, 
	                       CGAL::Polyhedron_items_3, 
						   CGAL::HalfedgeDS_list> CgalPolyhedron;

// Compute the area of all facets in a CGAL::Polyhedron_3 and stores it in 
// facetAreas.
// TPolyhedron is a type of CGAL::Polyhedron_3.
// TFacetAreas is a property map which associates the facet area to facet in 
// the CGAL::Polyhdeon_3.
// TFacetNormals is a property map which associates a normal vector to facet in 
// the CGAL::Polyhdeon_3.
template<class TPolyhedron, class TFacetAreas, class TFacetNormals>
void computeFacetAreas(const TPolyhedron& polyhedron, TFacetAreas* facetAreas, const TFacetNormals& facetNormals)
{
	if(facetAreas == 0)
	{
		return;
	}
	
	typename TPolyhedron::Facet_const_iterator _begin = polyhedron.facets_begin();
	typename TPolyhedron::Facet_const_iterator _end   = polyhedron.facets_end();
	
	SMeshLib::Operations::ComputeFacetArea<TPolyhedron, TFacetNormals> _computeFacetArea(facetNormals);
	CGAL_For_all(_begin, _end)
	{
		facetAreas->setValue(&*_begin, _computeFacetArea(*_begin));
	}
}

// Compute the normal of all facets in a CGAL::Polyhedron_3 and stores it in facetNormals.
// TPolyhedron is a type of CGAL::Polyhedron_3.
// TFacetNormals is a property map which associates a normal vector to facet in the CGAL::Polyhdeon_3. 
template<class TPolyhedron, class TFacetNormals>
void computeFacetNormals(const TPolyhedron& polyhedron, TFacetNormals* facetNormals)
{
	if(facetNormals == 0)
	{
		return;
	}
	
	typename TPolyhedron::Facet_const_iterator _begin = polyhedron.facets_begin();
	typename TPolyhedron::Facet_const_iterator _end   = polyhedron.facets_end();

	SMeshLib::Operations::ComputeFacetNormal<TPolyhedron> _computeFacetNormal;
	CGAL_For_all(_begin, _end)
	{
		facetNormals->setValue(&*_begin, _computeFacetNormal(*_begin));
	}
}

void testComputeFacetArea()
{
	CgalPolyhedron _poly;
	SMeshLib::IO::importOBJ("Venus.obj", &_poly);
	
	typedef SMeshLib::PropertyMap<const CgalPolyhedron::Facet*, CgalPolyhedron::Traits::Vector_3> FacetNormalPM;
	FacetNormalPM _facetNormals;
	computeFacetNormals(_poly, &_facetNormals);
	
	typedef SMeshLib::PropertyMap<const CgalPolyhedron::Facet*, double> FacetAreaPM;
	FacetAreaPM _facetAreas;
	computeFacetAreas(_poly, &_facetAreas, _facetNormals);
}
Downloads

ImportOBJ.h
PropertyMap.h
ComputeFacetNormal.h
ComputeFacetArea.h
TestComputeFacetArea.cpp
Venus.obj
ComputeFacetArea.zip


Computing normal of all vertices in CGAL::Polyhedron_3

In this post I will show how to compute normal vector at a vector in CGAL::Polyhedron_3.

ComputeVertexNormal() Functor

ComputeVertexNormal() is a thread-safe functor for computing the normal vector at a given vertex in a CGAL::Polyhedron_3. The normal vector at a vertex is the average of the normal vectors of all facets incident on the vertex. The facet normals must be be initialized using the ComputeVertexNormal()’s constructor. The code for computing the facet normals is presented in this post: Computing normal of all facets in CGAL::Polyhedron_3.

#ifndef _SMESHLIB_OPERATIONS_COMPUTEVERTEXNORMAL_H_
#define _SMESHLIB_OPERATIONS_COMPUTEVERTEXNORMAL_H_

#include "PropertyMap.h"

namespace SMeshLib   {
namespace Operations {
;

// The ComputeVertexNormal is a functor (delegate) to compute the normal of a vertex in CGAL::Polyhdeon_3.
// operator() is thread-safe.
// TPolyhedron is a type of CGAL::Polyhdeon_3.
// TFacetNormals is a property map which associates a normal vector to each facet in the CGAL::Polyhdeon_3.
// The vertex normal is the average of all facet normals incident on it.
template<class TPolyhedron, class TFacetNormals>
struct ComputeVertexNormal
{
public:
	
	// Redefine types from TPoly for convenience.
	typedef typename TPolyhedron::Vertex                                  Vertex;
	typedef typename TPolyhedron::Facet                                   Facet;
	typedef typename TPolyhedron::Traits::Vector_3                        Vector3;
	typedef typename TPolyhedron::Halfedge_around_vertex_const_circulator HalfEdgeConstCirculator;
	
	// Return type of operator() required by QtConcurrent.
	typedef Vector3 result_type;
	
public:
	
	ComputeVertexNormal(const TFacetNormals& facetNormals_)
		: facetNormals(facetNormals_)
	{}
	
	// Compute normal of the given vertex.
	inline Vector3 operator() (const Vertex& v) const
	{
		Vector3                 n = CGAL::NULL_VECTOR;
		HalfEdgeConstCirculator s = v.vertex_begin();
		HalfEdgeConstCirculator e = s;
		CGAL_For_all(s, e)
		{
			// Border edge doesn't have facet and hence no normal.
			if(!s->is_border())
			{
				n = n + facetNormals.value(&*(s->facet()));
			}
		}
		return n/std::sqrt(n*n);
	}
	
public:
	
	const TFacetNormals& facetNormals;
};

};	// End namespace Operations.
};	// End namespace SMeshLib.

#endif // _SMESHLIB_OPERATIONS_COMPUTEVERTEXNORMAL_H_
Using ComputeVertexNormal() Functor

Normal vector at a vertex v can be computed as Vector3 normal = ComputeVertexNormal(f); .

For most purposes, it is better to compute area of all facets once and cache them for later use. It is best to store the results in an associative container which associates the facet handle with the area. In the following example, I use PropertyMap which is a wrapper for std::set.

#include "ImportOBJ.h"
#include "ComputeFacetNormal.h"
#include "ComputeVertexNormal.h"
#include "PropertyMap.h"
#include "CGAL/Simple_cartesian.h"
#include <CGAL/Polyhedron_items_3.h>
#include "CGAL/HalfedgeDS_list.h"
#include "CGAL/Polyhedron_3.h"

typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Polyhedron_3<Kernel, 
	                       CGAL::Polyhedron_items_3, 
						   CGAL::HalfedgeDS_list> CgalPolyhedron;

// Compute the normal of all vertices in a CGAL::Polyhedron_3 and stores it in 
// vertexNormals.
// TPolyhedron is a type of CGAL::Polyhedron_3.
// TVertexNormals is a property map which associates a normal vector to vertex 
// in the CGAL::Polyhdeon_3.
// TFacetNormals is a property map which associates a normal vector to facet 
// in the CGAL::Polyhdeon_3.
template<class TPolyhedron, class TVertexNormals, class TFacetNormals>
void computeVertexNormals(const TPolyhedron& polyhedron, TVertexNormals* vertexNormals, const TFacetNormals& facetNormals)
{
	if(vertexNormals == 0)
	{
		return;
	}
	
	typename TPolyhedron::Vertex_const_iterator _begin = polyhedron.vertices_begin();
	typename TPolyhedron::Vertex_const_iterator _end   = polyhedron.vertices_end();
	
	SMeshLib::Operations::ComputeVertexNormal<TPolyhedron, TFacetNormals> _computeVertexNormal(facetNormals);
	CGAL_For_all(_begin, _end)
	{
		vertexNormals->setValue(&*_begin, _computeVertexNormal(*_begin));
	}
}

// Compute the normal of all facets in a CGAL::Polyhedron_3 and stores it in facetNormals.
// TPolyhedron is a type of CGAL::Polyhedron_3.
// TFacetNormals is a property map which associates a normal vector to facet in the CGAL::Polyhdeon_3. 
template<class TPolyhedron, class TFacetNormals>
void computeFacetNormals(const TPolyhedron& polyhedron, TFacetNormals* facetNormals)
{
	if(facetNormals == 0)
	{
		return;
	}
	
	typename TPolyhedron::Facet_const_iterator _begin = polyhedron.facets_begin();
	typename TPolyhedron::Facet_const_iterator _end   = polyhedron.facets_end();

	SMeshLib::Operations::ComputeFacetNormal<TPolyhedron> _computeFacetNormal;
	CGAL_For_all(_begin, _end)
	{
		facetNormals->setValue(&*_begin, _computeFacetNormal(*_begin));
	}
}

void testComputeVertexNormal()
{
	CgalPolyhedron _poly;
	SMeshLib::IO::importOBJ("Venus.obj", &_poly);
	
	typedef SMeshLib::PropertyMap<const CgalPolyhedron::Facet*, CgalPolyhedron::Traits::Vector_3> FacetNormalPM;
	FacetNormalPM _facetNormals;
	computeFacetNormals(_poly, &_facetNormals);
	
	typedef SMeshLib::PropertyMap<const CgalPolyhedron::Vertex*, CgalPolyhedron::Traits::Vector_3> VertexNormalPM;
	VertexNormalPM _vertexNormals;
	computeVertexNormals(_poly, &_vertexNormals, _facetNormals);
}
Downloads

ImportOBJ.h
PropertyMap.h
ComputeFacetNormal.h
ComputeVertexNormal.h
TestComputeVertexNormal.cpp
Venus.obj
ComputeVertexNormal.zip


Computing normal of all facets in CGAL::Polyhedron_3

In this post I will show how to compute normal vector of a facet in CGAL::Polyhedron_3.

ComputeFacetNormal() Functor

ComputeFacetNormal() is a thread-safe functor for computing the normal vector of a given facet in a CGAL::Polyhedron_3. The facet must be a planar polygon with arbitrary number of sides.

#ifndef _SMESHLIB_OPERATIONS_COMPUTEFACETNORMAL_H_
#define _SMESHLIB_OPERATIONS_COMPUTEFACETNORMAL_H_

namespace SMeshLib   {
namespace Operations {
;

// The ComputeFacetNormal is a functor (delegate) to compute the normal of a facet in CGAL::Polyhdeon_3.
// ComputeFacetNormal is thread-safe.
// TPolyhedron is a type of CGAL::Polyhdeon_3.
template<class TPolyhedron>
struct ComputeFacetNormal
{
public:
	
	// Redefine types from TPolyhedron for convenience.
	typedef typename TPolyhedron::Facet                 Facet;
	typedef typename TPolyhedron::Halfedge_const_handle HalfedgeConstHandle;
	typedef typename TPolyhedron::Traits::Point_3       Point3;
	typedef typename TPolyhedron::Traits::Vector_3      Vector3;
	
	// Return type of operator() required by QtConcurrent.
	typedef Vector3 result_type;
	
public:
	
	// Compute normal of the given facet.
	// Facet can be triangle, quadrilateral or a polygon as long as its planar.
	// Use first three vertices to compute the normal.
	inline Vector3 operator() (const Facet& f) const
	{
		HalfedgeConstHandle h  = f.halfedge();
		Point3              p1 = h->vertex()->point();
		Point3              p2 = h->next()->vertex()->point();
		Point3              p3 = h->next()->next()->vertex()->point();
		Vector3             n  = CGAL::cross_product(p2-p1, p3-p1);
		return n / std::sqrt(n*n);
	}
};

};	// End namespace Operations.
};	// End namespace SMeshLib.

#endif // _SMESHLIB_OPERATIONS_COMPUTEFACETNORMAL_H_
Using ComputeFacetNormal() Functor

Normal vector of a facet f can be computed as Vector3 normal = ComputeFacetNormal(f);.

For most purposes, it is better to compute area of all facets once and cache them for later use. It is best to store the results in an associative container which associates the facet handle with the area. In the following example, I use PropertyMap which is a wrapper for std::set.

#include "ImportOBJ.h"
#include "ComputeFacetNormal.h"
#include "PropertyMap.h"
#include "CGAL/Simple_cartesian.h"
#include "CGAL/Polyhedron_items_3.h"
#include "CGAL/HalfedgeDS_list.h"
#include "CGAL/Polyhedron_3.h"

typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Polyhedron_3<Kernel, 
	                   CGAL::Polyhedron_items_3, 
			   CGAL::HalfedgeDS_list> CgalPolyhedron;

// Compute the normal of all facets in a CGAL::Polyhedron_3 and stores it in 
// facetNormals.
// TPolyhedron is a type of CGAL::Polyhedron_3.
// TFacetNormals is a property map which associates a normal vector to facet in 
// the CGAL::Polyhdeon_3. 
template<class TPolyhedron, class TFacetNormals>
void computeFacetNormals(const TPolyhedron& polyhedron, TFacetNormals* facetNormals)
{
	if(facetNormals == 0)
	{
		return;
	}
	
	typename TPolyhedron::Facet_const_iterator _begin = polyhedron.facets_begin();
	typename TPolyhedron::Facet_const_iterator _end   = polyhedron.facets_end();

	SMeshLib::Operations::ComputeFacetNormal<TPolyhedron> _computeFacetNormal;
	CGAL_For_all(_begin, _end)
	{
		facetNormals->setValue(&*_begin, _computeFacetNormal(*_begin));
	}
}

void testComputeFacetNormal()
{
	CgalPolyhedron _poly;
	SMeshLib::IO::importOBJ("Venus.obj", &_poly);
	
	typedef SMeshLib::PropertyMap<const CgalPolyhedron::Facet*, CgalPolyhedron::Traits::Vector_3> FacetNormalPM;
	FacetNormalPM _facetNormals;
	computeFacetNormals(_poly, &_facetNormals);
}
Downloads

ImportOBJ.h
PropertyMap.h
ComputeFacetNormal.h
TestComputeFacetNormal.cpp
Venus.obj
ComputeFacetNormal.zip