mergeSegment = function(segment1, segment2) {
	var merged = [];
	
	if(segment1[0] <= segment2[0]) {
		if(segment1[1] < segment2[0]) {
			merged = [segment1, segment2];
		}
		else {
			if(segment1[1] >= segment2[1])
				merged = [segment1];
			else 
				merged = [[segment1[0], segment2[1]]];
		}
	}
	else {
		if(segment2[1] < segment1[0]) {
			merged = [segment2, segment1];
		}
		else {
			if(segment2[1] >= segment1[1])
				merged = [segment2];
			else 
				merged = [[segment2[0], segment1[1]]];
		}
	}
	return merged;
}

compareSegment = function(segment1, segment2) {
	// inclusi o coincidenti
	if((segment1[0] >= segment2[0]) && (segment1[1] <= segment2[1]))
		return 0;
	if((segment1[0] <= segment2[0]) && (segment1[1] >= segment2[1]))
		return 0;
	// esterni
	if((segment1[1] < segment2[0]) || ((segment1[0] > segment2[1])))
		return 1;
	// intersecanti
	return -1;
}

compareSegments = function(s1, s2) {
	return (s1[0] - s2[0]);
}

/**
 * mergeAll: merge indices
 * parameters: indices = Array of Array of indices (index = [start, end])
 * Example: indices = [[[1,2], [4,5]], [[0,5], [7,11]]];
 */

mergeAll = function(indices) {
	var m = [];
	
	// first of all: creates a 1-dimension array with all data
	for(var i=0; i<indices.length; i++) {
		m = m.concat(indices[i]);
	}
	
	//
	// second step: sort the array
	// for our purposes a segment is 'lower than' another segment if the left value of the segment 
	// is lower than the left value of the other segment. In other words:
	// [a, b] < [c, d] if a < c
	//
	m = m.sort(compareSegments);
	
	var m2 = [];
	
	//
	// merging procedure:
	// the procedure uses the functions: 
	// [1] 'compareSegment'.
	// when two segment are equals or included compareSegment returns 0
	// when two segment are intersecting compareSegment returns -1
	// when two segment are external (no intersection) compareSegment returns 1
	//
	// [2] 'mergeSegment'
	// returns the "union" of two segments
	//
	var current = m[0];
	for(var i=0; i<m.length; i++) {
		var cfr = compareSegment(current, m[i]);
		switch(cfr) {
		case 0:
		case -1:
			// if segments are the same or intersected the result is the merged segment
			current = mergeSegment(current, m[i])[0];
			break;
		default:
			// if segments are external mergeSegment produce two segments: the first is ready to be stored in the output vector
			// the second is to be compared with others
			var s = mergeSegment(current, m[i]);
			m2[m2.length] = s[0];
			current = s[1];
			break;
		}
	}
	
	if(m2.length == 0) {
		m2[0] = current;
	}
	else if((current[0] != m2[m2.length-1][0]) || (current[1] != m2[m2.length-1][1]))
		m2[m2.length] = current;	
	return m2;
}
