bokeh_util.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from __future__ import annotations
  2. from typing import TYPE_CHECKING, cast
  3. from contourpy import FillType, LineType
  4. from contourpy.array import offsets_from_codes
  5. from contourpy.convert import convert_lines
  6. from contourpy.dechunk import dechunk_lines
  7. if TYPE_CHECKING:
  8. from contourpy._contourpy import (
  9. CoordinateArray,
  10. FillReturn,
  11. LineReturn,
  12. LineReturn_ChunkCombinedNan,
  13. )
  14. def filled_to_bokeh(
  15. filled: FillReturn,
  16. fill_type: FillType,
  17. ) -> tuple[list[list[CoordinateArray]], list[list[CoordinateArray]]]:
  18. xs: list[list[CoordinateArray]] = []
  19. ys: list[list[CoordinateArray]] = []
  20. if fill_type in (FillType.OuterOffset, FillType.ChunkCombinedOffset,
  21. FillType.OuterCode, FillType.ChunkCombinedCode):
  22. have_codes = fill_type in (FillType.OuterCode, FillType.ChunkCombinedCode)
  23. for points, offsets in zip(*filled):
  24. if points is None:
  25. continue
  26. if have_codes:
  27. offsets = offsets_from_codes(offsets)
  28. xs.append([]) # New outer with zero or more holes.
  29. ys.append([])
  30. for i in range(len(offsets)-1):
  31. xys = points[offsets[i]:offsets[i+1]]
  32. xs[-1].append(xys[:, 0])
  33. ys[-1].append(xys[:, 1])
  34. elif fill_type in (FillType.ChunkCombinedCodeOffset, FillType.ChunkCombinedOffsetOffset):
  35. for points, codes_or_offsets, outer_offsets in zip(*filled):
  36. if points is None:
  37. continue
  38. for j in range(len(outer_offsets)-1):
  39. if fill_type == FillType.ChunkCombinedCodeOffset:
  40. codes = codes_or_offsets[outer_offsets[j]:outer_offsets[j+1]]
  41. offsets = offsets_from_codes(codes) + outer_offsets[j]
  42. else:
  43. offsets = codes_or_offsets[outer_offsets[j]:outer_offsets[j+1]+1]
  44. xs.append([]) # New outer with zero or more holes.
  45. ys.append([])
  46. for k in range(len(offsets)-1):
  47. xys = points[offsets[k]:offsets[k+1]]
  48. xs[-1].append(xys[:, 0])
  49. ys[-1].append(xys[:, 1])
  50. else:
  51. raise RuntimeError(f"Conversion of FillType {fill_type} to Bokeh is not implemented")
  52. return xs, ys
  53. def lines_to_bokeh(
  54. lines: LineReturn,
  55. line_type: LineType,
  56. ) -> tuple[CoordinateArray | None, CoordinateArray | None]:
  57. lines = convert_lines(lines, line_type, LineType.ChunkCombinedNan)
  58. lines = dechunk_lines(lines, LineType.ChunkCombinedNan)
  59. if TYPE_CHECKING:
  60. lines = cast(LineReturn_ChunkCombinedNan, lines)
  61. points = lines[0][0]
  62. if points is None:
  63. return None, None
  64. else:
  65. return points[:, 0], points[:, 1]