code: def invalidate(self, proj):
      self.painter = BatchPainter()
      x, y = proj.lonlat_to_screen(self.data["lon"], self.data["lat"])
  
      w = x.max() - x.min()
      h = y.max() - y.min()
      w = np.ceil(w / 2) * 2
      h = np.ceil(h / 2) * 2
      l = max(w, h)
  
      root = QuadTree(x.min(), x.min() + l, y.min() + l, y.min())
      maxarea = (root.right - root.left) * (root.top - root.bottom)
      queue = [root]
      done = []
      while len(queue) > 0:
          qt = queue.pop()
          if qt.can_split(x, y):
              queue.extend(qt.split())
          else:
              done.append(qt)
  
      print(len(queue), len(done))
  
      if self.cmap is not None:
          for qt in done:
              area = (qt.right - qt.left) * (qt.top - qt.bottom)
              self.painter.set_color(
                  self.cmap.to_color(1 + area, 1 + maxarea, "log")
              )
              self.painter.rect(qt.left, qt.top, qt.right, qt.bottom)
      else:
          for qt in done:
              self.painter.linestrip(
                  [qt.left, qt.right, qt.right, qt.left],
                  [qt.top, qt.top, qt.bottom, qt.bottom],
                  closed=True,
              )
  
file_path: geoplotlib/examples/quadtree.py
imports: import geoplotlib
  from geoplotlib.layers import BaseLayer
  from geoplotlib.core import BatchPainter
  from geoplotlib.utils import BoundingBox
  import numpy
label_desc: Use image node_id 2 for calling the QuadsLayer obj's underlying member method code with example usage: obj.invalidate(proj) without return types