File size: 1,884 Bytes
eebc40f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { useCallback, useMemo } from 'react';
import * as d3 from 'd3';

/**
 * Hook pour la virtualisation/culling des glyphes
 * Ne rend que les glyphes visibles dans le viewport
 */
export const useViewportCulling = (positions, viewportBounds, padding = 200) => {
  
  // Fonction pour calculer les glyphes visibles
  const getVisibleGlyphs = useCallback((positions, bounds, padding) => {
    if (!positions.length || !bounds) return positions;
    
    const { x, y, width, height, scale } = bounds;
    
    // Étendre les bounds avec du padding
    const visibleBounds = {
      minX: (x - padding) / scale,
      maxX: (x + width + padding) / scale,
      minY: (y - padding) / scale,
      maxY: (y + height + padding) / scale
    };
    
    // Filtrer les positions visibles
    return positions.filter(position => {
      return position.x >= visibleBounds.minX &&
             position.x <= visibleBounds.maxX &&
             position.y >= visibleBounds.minY &&
             position.y <= visibleBounds.maxY;
    });
  }, []);

  // Mémoriser les glyphes visibles
  const visiblePositions = useMemo(() => {
    return getVisibleGlyphs(positions, viewportBounds, padding);
  }, [positions, viewportBounds, padding, getVisibleGlyphs]);

  // Fonction pour obtenir les bounds du viewport
  const getViewportBounds = useCallback((svg, viewportGroup) => {
    if (!svg || !viewportGroup) return null;
    
    const transform = d3.zoomTransform(svg.node());
    const svgRect = svg.node().getBoundingClientRect();
    
    return {
      x: -transform.x / transform.k,
      y: -transform.y / transform.k,
      width: svgRect.width / transform.k,
      height: svgRect.height / transform.k,
      scale: transform.k
    };
  }, []);

  return {
    visiblePositions,
    getViewportBounds,
    totalCount: positions.length,
    visibleCount: visiblePositions.length
  };
};