kaxe 1.4.4.dev13__tar.gz → 1.4.4.dev14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. {kaxe-1.4.4.dev13/src/kaxe.egg-info → kaxe-1.4.4.dev14}/PKG-INFO +1 -1
  2. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/pyproject.toml +1 -1
  3. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/helper.py +31 -0
  4. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/svg.py +50 -23
  5. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/window.py +36 -3
  6. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/function.py +2 -0
  7. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/point.py +21 -12
  8. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/grid.py +3 -2
  9. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14/src/kaxe.egg-info}/PKG-INFO +1 -1
  10. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/LICENSE +0 -0
  11. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/MANIFEST.in +0 -0
  12. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/README.md +0 -0
  13. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/setup.cfg +0 -0
  14. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/__init__.py +0 -0
  15. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/chart/__init__.py +0 -0
  16. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/chart/bar.py +0 -0
  17. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/chart/box.py +0 -0
  18. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/chart/pie.py +0 -0
  19. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/chart/qqplot.py +0 -0
  20. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/__init__.py +0 -0
  21. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/axis.py +0 -0
  22. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/color.py +0 -0
  23. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/backend.py +0 -0
  24. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/camera.py +0 -0
  25. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/helper.py +0 -0
  26. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/hud.py +0 -0
  27. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/objects/__init__.py +0 -0
  28. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/objects/color.py +0 -0
  29. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/objects/line.py +0 -0
  30. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/objects/point.py +0 -0
  31. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/objects/pointer.py +0 -0
  32. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/objects/triangle.py +0 -0
  33. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/openglrender.py +0 -0
  34. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/d3/translator.py +0 -0
  35. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/draw.py +0 -0
  36. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/fileloader.py +0 -0
  37. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/legend.py +0 -0
  38. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/line.py +0 -0
  39. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/marker.py +0 -0
  40. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/profiler.py +0 -0
  41. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/round.py +0 -0
  42. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/shapes.py +0 -0
  43. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/styles.py +0 -0
  44. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/svg_pdf.py +0 -0
  45. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/symbol.py +0 -0
  46. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/core/text.py +0 -0
  47. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/data/__init__.py +0 -0
  48. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/data/excel.py +0 -0
  49. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/__init__.py +0 -0
  50. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/_lazy.py +0 -0
  51. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/__init__.py +0 -0
  52. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/arrow.py +0 -0
  53. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/bubble.py +0 -0
  54. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/contour.py +0 -0
  55. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/equation.py +0 -0
  56. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/fill.py +0 -0
  57. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/map.py +0 -0
  58. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/parameter.py +0 -0
  59. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d2/pillar.py +0 -0
  60. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d3/__init__.py +0 -0
  61. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d3/base.py +0 -0
  62. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d3/function.py +0 -0
  63. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d3/mesh.py +0 -0
  64. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d3/point.py +0 -0
  65. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/d3/potato.py +0 -0
  66. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/function.py +0 -0
  67. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/legend.py +0 -0
  68. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/mapdata.py +0 -0
  69. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/point.py +0 -0
  70. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/objects/text.py +0 -0
  71. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/__init__.py +0 -0
  72. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/_lazy.py +0 -0
  73. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/box.py +0 -0
  74. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/constants.py +0 -0
  75. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/d3/__init__.py +0 -0
  76. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/d3/axes.py +0 -0
  77. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/d3/geometry.py +0 -0
  78. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/d3/plot3d.py +0 -0
  79. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/d3/variants.py +0 -0
  80. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/double.py +0 -0
  81. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/empty.py +0 -0
  82. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/log.py +0 -0
  83. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/polar.py +0 -0
  84. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/standard.py +0 -0
  85. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/themes.py +0 -0
  86. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/zoom.py +0 -0
  87. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/plot/zoom_connector.py +0 -0
  88. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/__init__.py +0 -0
  89. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/__init__.py +0 -0
  90. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.bright-oblique.ttf +0 -0
  91. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.bright-roman.ttf +0 -0
  92. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.bright-semibold.ttf +0 -0
  93. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.bright-semiboldoblique.ttf +0 -0
  94. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.classical-serif-italic.ttf +0 -0
  95. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.concrete-bold.ttf +0 -0
  96. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.concrete-bolditalic.ttf +0 -0
  97. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.concrete-italic.ttf +0 -0
  98. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.concrete-roman.ttf +0 -0
  99. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-bold.ttf +0 -0
  100. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-boldoblique.ttf +0 -0
  101. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-demi-condensed-demicondensed.ttf +0 -0
  102. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-medium.ttf +0 -0
  103. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-oblique.ttf +0 -0
  104. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-bold.ttf +0 -0
  105. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-bolditalic.ttf +0 -0
  106. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-boldslanted.ttf +0 -0
  107. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-romanslanted.ttf +0 -0
  108. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-italic.ttf +0 -0
  109. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-roman.ttf +0 -0
  110. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.serif-upright-italic-uprightitalic.ttf +0 -0
  111. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bold.ttf +0 -0
  112. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bolditalic.ttf +0 -0
  113. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-italic.ttf +0 -0
  114. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-light.ttf +0 -0
  115. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-lightoblique.ttf +0 -0
  116. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-regular.ttf +0 -0
  117. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-italic.ttf +0 -0
  118. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-medium.ttf +0 -0
  119. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/computer-modern-family/readme.txt +0 -0
  120. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/logo-small.png +0 -0
  121. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/symbolcross.png +0 -0
  122. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/symboldonut.png +0 -0
  123. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/symbollollipop.png +0 -0
  124. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe/resources/symboltriangle.png +0 -0
  125. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe.egg-info/SOURCES.txt +0 -0
  126. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe.egg-info/dependency_links.txt +0 -0
  127. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe.egg-info/requires.txt +0 -0
  128. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/src/kaxe.egg-info/top_level.txt +0 -0
  129. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/tests/test.py +0 -0
  130. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/tests/test2.py +0 -0
  131. {kaxe-1.4.4.dev13 → kaxe-1.4.4.dev14}/tests/test3.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kaxe
3
- Version: 1.4.4.dev13
3
+ Version: 1.4.4.dev14
4
4
  Summary: A small graphing tool for functions, points, equations and more
5
5
  Author-email: Valter Yde Daugberg <valteryde@hotmail.com>
6
6
  Project-URL: Homepage, https://github.com/valteryde/kaxe
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kaxe"
3
- version = "1.4.4.dev13"
3
+ version = "1.4.4.dev14"
4
4
  authors = [
5
5
  { name="Valter Yde Daugberg", email="valteryde@hotmail.com" },
6
6
  ]
@@ -127,6 +127,37 @@ def insideBox(box, point):
127
127
  return True
128
128
 
129
129
 
130
+ def segment_break_threshold(parent) -> float:
131
+ """Pixel y delta above which a new polyline segment should start."""
132
+ box = parent.windowBox
133
+ return (box[3] - box[1]) * 0.45
134
+
135
+
136
+ def should_break_polyline_segment(
137
+ p1: tuple[float, float],
138
+ p2: tuple[float, float],
139
+ parent,
140
+ ) -> bool:
141
+ """Break when a segment looks like a wrap-around, not a normal diagonal."""
142
+ dx = abs(p2[0] - p1[0])
143
+ dy = abs(p2[1] - p1[1])
144
+ if dy <= segment_break_threshold(parent):
145
+ return False
146
+ return dy > dx * 1.5
147
+
148
+
149
+ def plot_window_clip_rect_svg(plot) -> tuple[float, float, float, float]:
150
+ """Return plot windowBox as an SVG clip rect (x, y, width, height), y-down."""
151
+ box = plot.windowBox
152
+ canvas_h = plot.getSize()[1]
153
+ return (
154
+ float(box[0]),
155
+ float(canvas_h - box[3]),
156
+ float(box[2] - box[0]),
157
+ float(box[3] - box[1]),
158
+ )
159
+
160
+
130
161
  def shell(a):
131
162
  def __shell__():
132
163
  return a
@@ -59,6 +59,7 @@ class SvgDocument:
59
59
  self._fondi_font_css: Optional[str] = None
60
60
  self._clip_defs: list[ET.Element] = []
61
61
  self._clip_counter = 0
62
+ self._active_group: Optional[ET.Element] = None
62
63
 
63
64
  @property
64
65
  def height(self) -> int:
@@ -71,12 +72,48 @@ class SvgDocument:
71
72
  def flip_y(self, y: float) -> float:
72
73
  return flip_y(y, self._height)
73
74
 
75
+ def _register_clip_rect(self, x: float, y: float, width: float, height: float) -> str:
76
+ clip_id = f"kaxe-clip-{self._clip_counter}"
77
+ self._clip_counter += 1
78
+ clip_path = ET.Element(
79
+ f"{{{SVG_NS}}}clipPath",
80
+ {"id": clip_id},
81
+ )
82
+ ET.SubElement(
83
+ clip_path,
84
+ f"{{{SVG_NS}}}rect",
85
+ {
86
+ "x": str(round(x, 3)),
87
+ "y": str(round(y, 3)),
88
+ "width": str(round(width, 3)),
89
+ "height": str(round(height, 3)),
90
+ },
91
+ )
92
+ self._clip_defs.append(clip_path)
93
+ return clip_id
94
+
95
+ def push_clip_layer(self, x: float, y: float, width: float, height: float) -> None:
96
+ """Clip subsequent elements to a rectangle in SVG top-down coordinates."""
97
+ clip_id = self._register_clip_rect(x, y, width, height)
98
+ group = ET.Element(
99
+ f"{{{SVG_NS}}}g",
100
+ {"clip-path": f"url(#{clip_id})"},
101
+ )
102
+ self._elements.append(group)
103
+ self._active_group = group
104
+
105
+ def pop_clip_layer(self) -> None:
106
+ self._active_group = None
107
+
74
108
  def add_element(self, tag: str, attribs: dict[str, Any]) -> ET.Element:
75
109
  el = ET.Element(
76
110
  f"{{{SVG_NS}}}{tag}",
77
111
  {k: str(v) for k, v in attribs.items() if v is not None},
78
112
  )
79
- self._elements.append(el)
113
+ if self._active_group is not None:
114
+ self._active_group.append(el)
115
+ else:
116
+ self._elements.append(el)
80
117
  return el
81
118
 
82
119
  def add_rect(
@@ -351,7 +388,10 @@ class SvgDocument:
351
388
  group = ET.Element(f"{{{SVG_NS}}}g", {"transform": transform})
352
389
  for child in list(inner):
353
390
  group.append(copy.deepcopy(child))
354
- self._elements.append(group)
391
+ if self._active_group is not None:
392
+ self._active_group.append(group)
393
+ else:
394
+ self._elements.append(group)
355
395
 
356
396
  def serialize(self) -> str:
357
397
  root = ET.Element(
@@ -420,33 +460,20 @@ def embed_svg_children(
420
460
  tx: float,
421
461
  ty: float,
422
462
  *,
423
- clip_size: Optional[tuple[float, float]] = None,
463
+ clip_rect: Optional[tuple[float, float, float, float]] = None,
424
464
  ) -> None:
425
- """Embed copied SVG children at top-left offset (SVG y-down coordinates)."""
465
+ """Embed copied SVG children at top-left offset (SVG y-down coordinates).
466
+
467
+ clip_rect is optional (x, y, width, height) in the embedded cell's local SVG space.
468
+ """
426
469
  if not children:
427
470
  return
428
471
  attribs: dict[str, str] = {
429
472
  "transform": f"translate({round(tx, 3)},{round(ty, 3)})",
430
473
  }
431
- if clip_size is not None:
432
- clip_w, clip_h = clip_size
433
- clip_id = f"kaxe-clip-{doc._clip_counter}"
434
- doc._clip_counter += 1
435
- clip_path = ET.Element(
436
- f"{{{SVG_NS}}}clipPath",
437
- {"id": clip_id},
438
- )
439
- ET.SubElement(
440
- clip_path,
441
- f"{{{SVG_NS}}}rect",
442
- {
443
- "x": "0",
444
- "y": "0",
445
- "width": str(round(clip_w, 3)),
446
- "height": str(round(clip_h, 3)),
447
- },
448
- )
449
- doc._clip_defs.append(clip_path)
474
+ if clip_rect is not None:
475
+ cx, cy, cw, ch = clip_rect
476
+ clip_id = doc._register_clip_rect(cx, cy, cw, ch)
450
477
  attribs["clip-path"] = f"url(#{clip_id})"
451
478
  group = ET.Element(f"{{{SVG_NS}}}g", attribs)
452
479
  for child in children:
@@ -418,7 +418,8 @@ class Window(AttrObject):
418
418
  self.__includeAllAgain__()
419
419
 
420
420
 
421
- self.shapes = [i[0] for i in sorted(self.shapes, key=lambda x: x[1])]
421
+ self.shape_layers = sorted(self.shapes, key=lambda x: x[1])
422
+ self.shapes = [i[0] for i in self.shape_layers]
422
423
 
423
424
  # add style padding
424
425
  self.addPaddingCondition(*self.getAttr('outerPadding'))
@@ -494,7 +495,23 @@ class Window(AttrObject):
494
495
  background = shapes.Rectangle(0, 0, winSize[0], winSize[1], color=self.getAttr('backgroundColor'))
495
496
  background.draw(doc)
496
497
 
497
- for shape in self.shapes:
498
+ box = self.windowBox
499
+ doc.push_clip_layer(
500
+ box[0],
501
+ winSize[1] - box[3],
502
+ box[2] - box[0],
503
+ box[3] - box[1],
504
+ )
505
+ for shape, z in getattr(self, "shape_layers", [(s, 0) for s in self.shapes]):
506
+ if z >= 2:
507
+ continue
508
+ shape.draw(doc)
509
+ if self.showProgressBar: pbar.update()
510
+ doc.pop_clip_layer()
511
+
512
+ for shape, z in getattr(self, "shape_layers", [(s, 0) for s in self.shapes]):
513
+ if z < 2:
514
+ continue
498
515
  shape.draw(doc)
499
516
  if self.showProgressBar: pbar.update()
500
517
 
@@ -524,7 +541,23 @@ class Window(AttrObject):
524
541
  background = shapes.Rectangle(0, 0, winSize[0], winSize[1], color=self.getAttr('backgroundColor'))
525
542
  background.draw(doc)
526
543
 
527
- for shape in self.shapes:
544
+ box = self.windowBox
545
+ doc.push_clip_layer(
546
+ box[0],
547
+ winSize[1] - box[3],
548
+ box[2] - box[0],
549
+ box[3] - box[1],
550
+ )
551
+ for shape, z in getattr(self, "shape_layers", [(s, 0) for s in self.shapes]):
552
+ if z >= 2:
553
+ continue
554
+ shape.draw(doc)
555
+ if self.showProgressBar: pbar.update()
556
+ doc.pop_clip_layer()
557
+
558
+ for shape, z in getattr(self, "shape_layers", [(s, 0) for s in self.shapes]):
559
+ if z < 2:
560
+ continue
528
561
  shape.draw(doc)
529
562
  if self.showProgressBar: pbar.update()
530
563
 
@@ -130,6 +130,8 @@ class Function2D:
130
130
  )
131
131
 
132
132
  if parent.inside(px, py) or parent.inside(*self.__lastPoint__):
133
+ if should_break_polyline_segment(self.__lastPoint__, (px, py), parent):
134
+ self.lineSegments.append([])
133
135
  self.lineSegments[-1].append(parent.clamp(self.__lastPoint__[0], self.__lastPoint__[1]))
134
136
  self.lineSegments[-1].append(parent.clamp(px, py))
135
137
  else:
@@ -136,25 +136,34 @@ class Points2D:
136
136
 
137
137
 
138
138
  def __finalizeConnectedLine__(self, parent, line_width):
139
- points = []
139
+ segments = [[]]
140
140
  for x_val, y_val in zip(self.x, self.y):
141
141
  px, py = parent.pixel(x_val, y_val)
142
142
  if px is None or py is None:
143
143
  continue
144
144
  if not parent.inside(px, py):
145
145
  continue
146
- points.append(parent.clamp(px, py))
146
+ point = parent.clamp(px, py)
147
+ if segments[-1] and should_break_polyline_segment(segments[-1][-1], point, parent):
148
+ segments.append([])
149
+ segments[-1].append(point)
147
150
 
148
- if len(points) < 2:
149
- return
150
- if len(points) == 2:
151
- x0, y0 = points[0]
152
- x1, y1 = points[1]
153
- line = shapes.Line(x0, y0, x1, y1, color=self.color, width=line_width, batch=self.batch, center=True)
154
- self.lines.append(line)
155
- return
156
-
157
- shapes.LineSegment(points, color=self.color, width=line_width, batch=self.batch)
151
+ for points in segments:
152
+ if len(points) < 2:
153
+ continue
154
+ if len(points) == 2:
155
+ x0, y0 = points[0]
156
+ x1, y1 = points[1]
157
+ line = shapes.Line(
158
+ x0, y0, x1, y1,
159
+ color=self.color,
160
+ width=line_width,
161
+ batch=self.batch,
162
+ center=True,
163
+ )
164
+ self.lines.append(line)
165
+ continue
166
+ shapes.LineSegment(points, color=self.color, width=line_width, batch=self.batch)
158
167
 
159
168
 
160
169
  def draw(self, *args, **kwargs):
@@ -111,6 +111,8 @@ class Grid(AttrObject):
111
111
  plot.__included__ = []
112
112
  plot.__baked__ = False
113
113
  plot.__bakedImage__ = False
114
+ if hasattr(plot, "shape_layers"):
115
+ plot.shape_layers = []
114
116
  for axis in (getattr(plot, "firstAxis", None), getattr(plot, "secondAxis", None)):
115
117
  if axis is not None:
116
118
  axis.markers = []
@@ -327,13 +329,12 @@ class Grid(AttrObject):
327
329
  xml = plot.__ioBytes.read().decode("utf-8")
328
330
  root = parse_svg_root(xml)
329
331
  children, fondi_css = extract_svg_children(root)
330
- cell_w, cell_h = plot.getSize()
331
332
  embed_svg_children(
332
333
  doc,
333
334
  children,
334
335
  px,
335
336
  py,
336
- clip_size=(cell_w, cell_h),
337
+ clip_rect=plot_window_clip_rect_svg(plot),
337
338
  )
338
339
  merge_fondi_css(doc, fondi_css)
339
340
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kaxe
3
- Version: 1.4.4.dev13
3
+ Version: 1.4.4.dev14
4
4
  Summary: A small graphing tool for functions, points, equations and more
5
5
  Author-email: Valter Yde Daugberg <valteryde@hotmail.com>
6
6
  Project-URL: Homepage, https://github.com/valteryde/kaxe
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes