1616class SingleIntersector {
1717 #annotation;
1818
19- # minX = Infinity ;
19+ minX = Infinity ;
2020
21- # minY = Infinity ;
21+ minY = Infinity ;
2222
23- # maxX = - Infinity ;
23+ maxX = - Infinity ;
2424
25- # maxY = - Infinity ;
25+ maxY = - Infinity ;
2626
2727 #quadPoints = null ;
2828
@@ -40,30 +40,21 @@ class SingleIntersector {
4040 if ( ! quadPoints ) {
4141 // If there are no quad points, we use the rectangle to determine the
4242 // bounds of the annotation.
43- [ this . # minX, this . # minY, this . # maxX, this . # maxY] = annotation . data . rect ;
43+ [ this . minX , this . minY , this . maxX , this . maxY ] = annotation . data . rect ;
4444 return ;
4545 }
4646
4747 for ( let i = 0 , ii = quadPoints . length ; i < ii ; i += 8 ) {
48- this . # minX = Math . min ( this . # minX, quadPoints [ i ] ) ;
49- this . # maxX = Math . max ( this . # maxX, quadPoints [ i + 2 ] ) ;
50- this . # minY = Math . min ( this . # minY, quadPoints [ i + 5 ] ) ;
51- this . # maxY = Math . max ( this . # maxY, quadPoints [ i + 1 ] ) ;
48+ this . minX = Math . min ( this . minX , quadPoints [ i ] ) ;
49+ this . maxX = Math . max ( this . maxX , quadPoints [ i + 2 ] ) ;
50+ this . minY = Math . min ( this . minY , quadPoints [ i + 5 ] ) ;
51+ this . maxY = Math . max ( this . maxY , quadPoints [ i + 1 ] ) ;
5252 }
5353 if ( quadPoints . length > 8 ) {
5454 this . #quadPoints = quadPoints ;
5555 }
5656 }
5757
58- overlaps ( other ) {
59- return ! (
60- this . #minX >= other . #maxX ||
61- this . #maxX <= other . #minX ||
62- this . #minY >= other . #maxY ||
63- this . #maxY <= other . #minY
64- ) ;
65- }
66-
6758 /**
6859 * Check if the given point intersects with the annotation's quad points.
6960 * The point (x, y) is supposed to be the center of the glyph.
@@ -72,12 +63,7 @@ class SingleIntersector {
7263 * @returns {boolean }
7364 */
7465 #intersects( x , y ) {
75- if (
76- this . #minX >= x ||
77- this . #maxX <= x ||
78- this . #minY >= y ||
79- this . #maxY <= y
80- ) {
66+ if ( this . minX >= x || this . maxX <= x || this . minY >= y || this . maxY <= y ) {
8167 return false ;
8268 }
8369
@@ -154,56 +140,91 @@ class SingleIntersector {
154140 }
155141}
156142
143+ // The grid is STEPS x STEPS.
144+ const STEPS = 64 ;
145+
157146class Intersector {
158- #intersectors = new Map ( ) ;
147+ #intersectors = [ ] ;
148+
149+ #grid = [ ] ;
150+
151+ #minX;
152+
153+ #minY;
154+
155+ #invXRatio;
156+
157+ #invYRatio;
159158
160159 constructor ( annotations ) {
160+ let minX = Infinity ;
161+ let minY = Infinity ;
162+ let maxX = - Infinity ;
163+ let maxY = - Infinity ;
164+ const intersectors = this . #intersectors;
161165 for ( const annotation of annotations ) {
162166 if ( ! annotation . data . quadPoints && ! annotation . data . rect ) {
163167 continue ;
164168 }
165169 const intersector = new SingleIntersector ( annotation ) ;
166- for ( const [ otherIntersector , overlapping ] of this . #intersectors) {
167- if ( otherIntersector . overlaps ( intersector ) ) {
168- if ( ! overlapping ) {
169- this . #intersectors. set ( otherIntersector , new Set ( [ intersector ] ) ) ;
170- } else {
171- overlapping . add ( intersector ) ;
170+ intersectors . push ( intersector ) ;
171+ minX = Math . min ( minX , intersector . minX ) ;
172+ minY = Math . min ( minY , intersector . minY ) ;
173+ maxX = Math . max ( maxX , intersector . maxX ) ;
174+ maxY = Math . max ( maxY , intersector . maxY ) ;
175+ }
176+ this . #minX = minX ;
177+ this . #minY = minY ;
178+ this . #invXRatio = ( STEPS - 1 ) / ( maxX - minX ) ;
179+ this . #invYRatio = ( STEPS - 1 ) / ( maxY - minY ) ;
180+ for ( const intersector of intersectors ) {
181+ const iMin = this . #getGridIndex( intersector . minX , intersector . minY ) ;
182+ const iMax = this . #getGridIndex( intersector . maxX , intersector . maxY ) ;
183+ const w = ( iMax - iMin ) % STEPS ;
184+ const h = Math . floor ( ( iMax - iMin ) / STEPS ) ;
185+ for ( let i = iMin ; i <= iMin + h * STEPS ; i += STEPS ) {
186+ for ( let j = 0 ; j <= w ; j ++ ) {
187+ let existing = this . #grid[ i + j ] ;
188+ if ( ! existing ) {
189+ this . #grid[ i + j ] = existing = [ ] ;
172190 }
191+ existing . push ( intersector ) ;
173192 }
174193 }
175- this . #intersectors. set ( intersector , null ) ;
176194 }
177195 }
178196
197+ #getGridIndex( x , y ) {
198+ const i = Math . floor ( ( x - this . #minX) * this . #invXRatio) ;
199+ const j = Math . floor ( ( y - this . #minY) * this . #invYRatio) ;
200+ return i >= 0 && i < STEPS && j >= 0 && j < STEPS ? i + j * STEPS : - 1 ;
201+ }
202+
179203 addGlyph ( transform , width , height , glyph ) {
180204 const x = transform [ 4 ] + width / 2 ;
181205 const y = transform [ 5 ] + height / 2 ;
182- let overlappingIntersectors ;
183- for ( const [ intersector , overlapping ] of this . #intersectors) {
184- if ( overlappingIntersectors ) {
185- if ( overlappingIntersectors . has ( intersector ) ) {
186- intersector . addGlyph ( x , y , glyph ) ;
187- } else {
188- intersector . disableExtraChars ( ) ;
189- }
190- continue ;
191- }
192- if ( ! intersector . addGlyph ( x , y , glyph ) ) {
193- continue ;
194- }
195- overlappingIntersectors = overlapping ;
206+ const index = this . #getGridIndex( x , y ) ;
207+ if ( index < 0 ) {
208+ return ;
209+ }
210+ const intersectors = this . #grid[ index ] ;
211+ if ( ! intersectors ) {
212+ return ;
213+ }
214+
215+ for ( const intersector of intersectors ) {
216+ intersector . addGlyph ( x , y , glyph ) ;
196217 }
197218 }
198219
199220 addExtraChar ( char ) {
200- for ( const intersector of this . #intersectors. keys ( ) ) {
221+ for ( const intersector of this . #intersectors) {
201222 intersector . addExtraChar ( char ) ;
202223 }
203224 }
204225
205226 setText ( ) {
206- for ( const intersector of this . #intersectors. keys ( ) ) {
227+ for ( const intersector of this . #intersectors) {
207228 intersector . setText ( ) ;
208229 }
209230 }
0 commit comments