;+ ; NAME: ; merge_ranges ; PURPOSE: ; Reduce a collection of ranges to a minimum set ; CATEGORY: ; gen/toolbox/match ; CALLING SEQUENCE: FUNCTION merge_ranges, rr, merge=merge ; INPUTS: ; rr array rr[2,n] or rr[2]; type: numerical ; set of ranges specified as pairs of ; start and end points ; OUTPUTS: ; result scalar; integer ; number of pairs in the minimum set ; OPTIONAL OUTPUT PARAMETERS: ; merge array rr[2,m] or rr[2] ; minimum set of ranges with overlaps removed. ; The start points rr[0,*] will be sorted; ; for all range pairs rr[1,i] > rr[0,i] ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; destroyvar ; PROCEDURE: ; Zero length ranges, rr[0,i]=rr[1,i], are removed ; If rr[1,i] < rr[0,i] the begin and endpoint are interchanged ; (i.e. [7,3] is interpreted as [3,7]) ; In the reduced set the start points of the ranges ; are sorted into ascending order. ; MODIFICATION HISTORY: ; APR-2013, Paul Hick (UCSD/CAIDA; pphick@caida.org) ;- IF n_elements(rr) EQ 0 THEN return, 0 nn = size(rr,/dim) IF nn[0] NE 2 THEN message, 'rr must be an array[2] or array[2,n]' ; Remove ranges of zero length nn = where( rr[0,*] NE rr[1,*] ) IF nn[0] EQ -1 THEN BEGIN destroyvar, merge RETURN, 0 ENDIF ss = rr[*,nn] ; Make sure end values are larger than start values IF size(ss,/n_dim) EQ 1 THEN nn=1 ELSE nn = (size(ss,/dim))[1] FOR i=0,nn-1 DO IF ss[0,i] GT ss[1,i] THEN ss[[0,1],i] = ss[[1,0],i] ; Sort the ranges so that the start points are ; sorted into ascending order. ss = ss[*,sort(reform(ss[0,*]))] ; Start from the first range nt = 0 mm = ss[*,0] FOR ns=1,nn-1 DO BEGIN IF ss[0,ns] GT mm[1,nt] THEN BEGIN ; Range starts later than end of previous range: new range mm = [[mm],[ss[*,ns]]] nt++ ENDIF ELSE BEGIN ; Range overlaps with previous range with endpoint ; extending past endpoint of previous range. ; Attach the tail end to the previous range. mm[1,nt] >= ss[1,ns] ENDELSE ENDFOR merge = mm RETURN, n_elements(merge)/2 & END