@@ -93,18 +93,40 @@ export const dedupeRects = (rects: Shape[], threshold = 0.1): Shape[] => {
9393 return dedupedRects ;
9494} ;
9595
96- export const combineRectsByRow = ( rects : Shape [ ] ) : Shape [ ] => {
97- const dedupedRects = dedupeRects ( rects ) ;
98-
99- const rows = dedupedRects . reduce ( ( groups , rect ) => {
100- const { y } = rect ;
101- const roundedY = Math . round ( y ) ;
102- groups [ roundedY ] = groups [ roundedY ] || [ ] ;
103- groups [ roundedY ] . push ( rect ) ;
104- return groups ;
105- } , { } as Record < number , Shape [ ] > ) ;
106-
107- return Object . values ( rows ) . map ( group => getBoundingRect ( group ) ) ;
96+ export const combineRects = ( rects : Shape [ ] ) : Shape [ ] => {
97+ const result : Shape [ ] = [ ] ;
98+
99+ dedupeRects ( rects ) . forEach ( rect => {
100+ const { height, width, x, y } = rect ;
101+ const lastRect = result . pop ( ) ;
102+
103+ if ( ! lastRect ) {
104+ result . push ( rect ) ;
105+ return ;
106+ }
107+
108+ // This algorithm employs a hueristic that assumes rects are returned in ascending y coordinate
109+ // followed by ascending x coordinate.
110+ // If there is already a previous rect, check first to see if the current rect is approximately
111+ // close enough (in both the x and y coordinate) to be considered as part of the same rect
112+ // If it is not close enough then add the current rect as a separate rect in the array
113+ const { height : lastHeight , width : lastWidth , x : lastX , y : lastY } = lastRect ;
114+ const lastMaxX = lastX + lastWidth ;
115+ const thresholdX = getThreshold ( lastWidth , width , 0.3 ) ;
116+ const thresholdY = getThreshold ( lastHeight , height , 0.6 ) ;
117+ const isXCloseEnough = Math . abs ( x - lastMaxX ) < thresholdX ;
118+ const isYCloseEnough = Math . abs ( y - lastY ) < thresholdY ;
119+
120+ // If rect is close enough, add the rect to the existing entry, otherwise add it as a new entry
121+ if ( isXCloseEnough && isYCloseEnough ) {
122+ result . push ( getBoundingRect ( [ lastRect , rect ] ) ) ;
123+ } else {
124+ result . push ( lastRect ) ;
125+ result . push ( rect ) ;
126+ }
127+ } ) ;
128+
129+ return result ;
108130} ;
109131
110132export const getShapeRelativeToContainer = ( shape : Shape , containerShape : Shape ) : Shape => {
0 commit comments