kaxe 1.5.5.dev0__tar.gz → 1.5.6__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.
- {kaxe-1.5.5.dev0/src/kaxe.egg-info → kaxe-1.5.6}/PKG-INFO +1 -1
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/pyproject.toml +1 -1
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/helper.py +26 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/contour.py +94 -70
- {kaxe-1.5.5.dev0 → kaxe-1.5.6/src/kaxe.egg-info}/PKG-INFO +1 -1
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/LICENSE +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/MANIFEST.in +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/README.md +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/setup.cfg +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/_require_3d.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/chart/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/chart/bar.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/chart/box.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/chart/pie.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/chart/qqplot.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/axis.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/bounds.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/color.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/backend.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/camera.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/helper.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/hud.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/objects/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/objects/color.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/objects/line.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/objects/point.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/objects/pointer.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/objects/triangle.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/openglrender.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/d3/translator.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/draw.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/fileloader.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/ipython_display.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/legend.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/line.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/marker.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/profiler.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/progress.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/round.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/shapes.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/styles.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/svg.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/svg_pdf.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/symbol.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/text.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/core/window.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/data/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/data/excel.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/_lazy.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/arrow.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/bubble.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/equation.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/fill.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/function.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/inequality.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/map.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/parameter.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/pillar.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d2/point.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d3/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d3/base.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d3/function.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d3/mesh.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d3/point.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/d3/potato.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/function.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/legend.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/mapdata.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/point.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/objects/text.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/_lazy.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/box.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/constants.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/d3/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/d3/axes.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/d3/geometry.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/d3/plot3d.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/d3/variants.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/double.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/empty.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/grid.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/log.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/polar.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/standard.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/themes.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/zoom.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/plot/zoom_connector.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/codec.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/context.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/document.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/registry.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/sample.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/sampled_curve.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/serializers.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/project/window.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/__init__.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-oblique.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-roman.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-semibold.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-semiboldoblique.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.classical-serif-italic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bold.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bolditalic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-italic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-roman.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-bold.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-boldoblique.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-demi-condensed-demicondensed.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-medium.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-oblique.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-bold.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-bolditalic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-boldslanted.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-romanslanted.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-italic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-roman.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-upright-italic-uprightitalic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bold.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bolditalic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-italic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-light.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-lightoblique.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-regular.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-italic.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-medium.ttf +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/readme.txt +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/logo-small.png +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/symbolcross.png +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/symboldonut.png +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/symbollollipop.png +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/symboltriangle.png +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe.egg-info/SOURCES.txt +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe.egg-info/dependency_links.txt +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe.egg-info/requires.txt +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe.egg-info/top_level.txt +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/tests/test.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/tests/test2.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/tests/test3.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/tests/test_4.py +0 -0
- {kaxe-1.5.5.dev0 → kaxe-1.5.6}/tests/test_5.py +0 -0
|
@@ -71,6 +71,32 @@ def contour_label_angle(polyline, index):
|
|
|
71
71
|
return angle
|
|
72
72
|
|
|
73
73
|
|
|
74
|
+
def bbox_overlaps(a, b, padding=0):
|
|
75
|
+
"""Return True if two axis-aligned boxes overlap.
|
|
76
|
+
|
|
77
|
+
Each box is ``(left, top, width, height)`` as returned by ``Text.getBoundingBox()``.
|
|
78
|
+
"""
|
|
79
|
+
ax, ay, aw, ah = a
|
|
80
|
+
bx, by, bw, bh = b
|
|
81
|
+
|
|
82
|
+
a_center = (ax + aw / 2, ay + ah / 2)
|
|
83
|
+
b_center = (bx + bw / 2, by + bh / 2)
|
|
84
|
+
a_size = (aw + 2 * padding, ah + 2 * padding)
|
|
85
|
+
b_size = (bw + 2 * padding, bh + 2 * padding)
|
|
86
|
+
|
|
87
|
+
a_top_right = (a_center[0] + a_size[0] / 2, a_center[1] + a_size[1] / 2)
|
|
88
|
+
a_bottom_left = (a_center[0] - a_size[0] / 2, a_center[1] - a_size[1] / 2)
|
|
89
|
+
b_top_right = (b_center[0] + b_size[0] / 2, b_center[1] + b_size[1] / 2)
|
|
90
|
+
b_bottom_left = (b_center[0] - b_size[0] / 2, b_center[1] - b_size[1] / 2)
|
|
91
|
+
|
|
92
|
+
return not (
|
|
93
|
+
a_top_right[0] < b_bottom_left[0]
|
|
94
|
+
or a_bottom_left[0] > b_top_right[0]
|
|
95
|
+
or a_top_right[1] < b_bottom_left[1]
|
|
96
|
+
or a_bottom_left[1] > b_top_right[1]
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
74
100
|
def resample_polyline(points, spacing):
|
|
75
101
|
"""
|
|
76
102
|
Emit points every `spacing` pixels along polyline arc length.
|
|
@@ -4,13 +4,13 @@ import math
|
|
|
4
4
|
from ...core.styles import *
|
|
5
5
|
from ...core.shapes import shapes
|
|
6
6
|
from ...core.symbol import symbol as symbols
|
|
7
|
-
from ...core.helper import contour_label_angle
|
|
7
|
+
from ...core.helper import bbox_overlaps, contour_label_angle, resample_polyline
|
|
8
8
|
from ...core.text import Text
|
|
9
9
|
from ...core.round import koundTeX
|
|
10
10
|
from ...plot import identities
|
|
11
11
|
from .equation import Equation, trace_contour_polylines
|
|
12
12
|
from types import FunctionType
|
|
13
|
-
from typing import Union
|
|
13
|
+
from typing import Optional, Union
|
|
14
14
|
from ...core.color import Colormaps, Colormap, to_rgba
|
|
15
15
|
|
|
16
16
|
|
|
@@ -47,30 +47,6 @@ def _simplify_polyline(polyline):
|
|
|
47
47
|
return simplified
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
def _point_at_arc_length(polyline, target):
|
|
51
|
-
if not polyline:
|
|
52
|
-
return 0, (0, 0)
|
|
53
|
-
|
|
54
|
-
if target <= 0:
|
|
55
|
-
return 0, polyline[0]
|
|
56
|
-
|
|
57
|
-
walked = 0.0
|
|
58
|
-
for i in range(1, len(polyline)):
|
|
59
|
-
dx = polyline[i][0] - polyline[i - 1][0]
|
|
60
|
-
dy = polyline[i][1] - polyline[i - 1][1]
|
|
61
|
-
seg_len = math.hypot(dx, dy)
|
|
62
|
-
if seg_len == 0:
|
|
63
|
-
continue
|
|
64
|
-
if walked + seg_len >= target:
|
|
65
|
-
t = (target - walked) / seg_len
|
|
66
|
-
px = polyline[i - 1][0] + t * dx
|
|
67
|
-
py = polyline[i - 1][1] + t * dy
|
|
68
|
-
return i, (px, py)
|
|
69
|
-
walked += seg_len
|
|
70
|
-
|
|
71
|
-
return len(polyline) - 1, polyline[-1]
|
|
72
|
-
|
|
73
|
-
|
|
74
50
|
def _closest_polyline_index(polyline, point):
|
|
75
51
|
best_index = 0
|
|
76
52
|
best_dist = float('inf')
|
|
@@ -82,7 +58,7 @@ def _closest_polyline_index(polyline, point):
|
|
|
82
58
|
return best_index
|
|
83
59
|
|
|
84
60
|
|
|
85
|
-
def
|
|
61
|
+
def _label_candidates(polyline, spacing):
|
|
86
62
|
polyline = _simplify_polyline(polyline)
|
|
87
63
|
if len(polyline) < 2:
|
|
88
64
|
return []
|
|
@@ -91,14 +67,16 @@ def _label_positions(polyline, spacing, max_labels=2):
|
|
|
91
67
|
if arc < spacing:
|
|
92
68
|
return []
|
|
93
69
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
index, point = _point_at_arc_length(polyline, target)
|
|
99
|
-
positions.append((point, _closest_polyline_index(polyline, point)))
|
|
70
|
+
candidates = []
|
|
71
|
+
for point in resample_polyline(polyline, spacing)[1:-1]:
|
|
72
|
+
index = _closest_polyline_index(polyline, point)
|
|
73
|
+
candidates.append((point, index, arc))
|
|
100
74
|
|
|
101
|
-
|
|
75
|
+
if not candidates and arc >= spacing:
|
|
76
|
+
mid_index = len(polyline) // 2
|
|
77
|
+
candidates.append((polyline[mid_index], mid_index, arc))
|
|
78
|
+
|
|
79
|
+
return candidates
|
|
102
80
|
|
|
103
81
|
|
|
104
82
|
def _point_in_expanded_bbox(x, y, bbox, padding):
|
|
@@ -132,7 +110,15 @@ class Contour:
|
|
|
132
110
|
label : bool, optional
|
|
133
111
|
Draw inline level labels on contour lines (default is True).
|
|
134
112
|
labelSpacing : int, optional
|
|
135
|
-
Minimum pixel spacing between
|
|
113
|
+
Minimum pixel spacing between label candidates along a contour (default is 100).
|
|
114
|
+
labelCollisionPadding : int, optional
|
|
115
|
+
Extra pixel gap required between placed label bounding boxes (default is 4).
|
|
116
|
+
labelMinArc : int, optional
|
|
117
|
+
Minimum polyline arc length to consider for labels (default is labelSpacing).
|
|
118
|
+
labelMaxBranches : int, optional
|
|
119
|
+
Maximum number of polylines per level to label (default is 1).
|
|
120
|
+
labelMaxPerLevel : int, optional
|
|
121
|
+
Hard cap on labels placed per level; unlimited when None (default is None).
|
|
136
122
|
labelColor : tuple, optional
|
|
137
123
|
Color of inline contour labels (default is black).
|
|
138
124
|
|
|
@@ -156,6 +142,10 @@ class Contour:
|
|
|
156
142
|
computePadding: int = 50,
|
|
157
143
|
label: bool = True,
|
|
158
144
|
labelSpacing: int = 100,
|
|
145
|
+
labelCollisionPadding: int = 4,
|
|
146
|
+
labelMinArc: Optional[int] = None,
|
|
147
|
+
labelMaxBranches: int = 1,
|
|
148
|
+
labelMaxPerLevel: Optional[int] = None,
|
|
159
149
|
labelColor=(0, 0, 0, 255),
|
|
160
150
|
):
|
|
161
151
|
self.batch = shapes.Batch()
|
|
@@ -168,6 +158,10 @@ class Contour:
|
|
|
168
158
|
self.lineThickness = lineThickness
|
|
169
159
|
self.label = label
|
|
170
160
|
self.labelSpacing = labelSpacing
|
|
161
|
+
self.labelCollisionPadding = labelCollisionPadding
|
|
162
|
+
self.labelMinArc = labelSpacing if labelMinArc is None else labelMinArc
|
|
163
|
+
self.labelMaxBranches = labelMaxBranches
|
|
164
|
+
self.labelMaxPerLevel = labelMaxPerLevel
|
|
171
165
|
self.labelColor = to_rgba(labelColor)
|
|
172
166
|
|
|
173
167
|
# color
|
|
@@ -208,12 +202,10 @@ class Contour:
|
|
|
208
202
|
if self.label and label_parent == identities.XYPLOT:
|
|
209
203
|
self.__finalizeLabels__(label_parent)
|
|
210
204
|
|
|
211
|
-
def
|
|
212
|
-
|
|
213
|
-
padding = max(2, fontSize // 8)
|
|
214
|
-
label_bboxes = []
|
|
205
|
+
def __collectCandidates__(self, parent):
|
|
206
|
+
candidates = []
|
|
215
207
|
|
|
216
|
-
for z, eq in self.__equations:
|
|
208
|
+
for level_index, (z, eq) in enumerate(self.__equations):
|
|
217
209
|
label_text = _format_contour_level(z, self.a, self.b, self.steps)
|
|
218
210
|
polylines = trace_contour_polylines(eq.dotsPosAbstract, parent)
|
|
219
211
|
polylines = sorted(
|
|
@@ -224,36 +216,68 @@ class Contour:
|
|
|
224
216
|
polylines = [
|
|
225
217
|
polyline
|
|
226
218
|
for polyline in polylines
|
|
227
|
-
if _polyline_arc_length(_simplify_polyline(polyline)) >= self.
|
|
228
|
-
][:
|
|
229
|
-
|
|
230
|
-
for polyline in polylines:
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
219
|
+
if _polyline_arc_length(_simplify_polyline(polyline)) >= self.labelMinArc
|
|
220
|
+
][: self.labelMaxBranches]
|
|
221
|
+
|
|
222
|
+
for branch_index, polyline in enumerate(polylines):
|
|
223
|
+
simplified = _simplify_polyline(polyline)
|
|
224
|
+
arc = _polyline_arc_length(simplified)
|
|
225
|
+
for candidate_index, (point, index, _) in enumerate(
|
|
226
|
+
_label_candidates(polyline, self.labelSpacing)
|
|
227
|
+
):
|
|
228
|
+
candidates.append({
|
|
229
|
+
"z": z,
|
|
230
|
+
"level_index": level_index,
|
|
231
|
+
"branch_index": branch_index,
|
|
232
|
+
"candidate_index": candidate_index,
|
|
233
|
+
"arc": arc,
|
|
234
|
+
"polyline": polyline,
|
|
235
|
+
"point": point,
|
|
236
|
+
"index": index,
|
|
237
|
+
"label_text": label_text,
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
candidates.sort(
|
|
241
|
+
key=lambda item: (-item["arc"], item["level_index"], item["branch_index"], item["candidate_index"])
|
|
242
|
+
)
|
|
243
|
+
return candidates
|
|
244
|
+
|
|
245
|
+
def __finalizeLabels__(self, parent):
|
|
246
|
+
fontSize = parent.getAttr('fontSize')
|
|
247
|
+
placed_bboxes = []
|
|
248
|
+
label_bboxes = []
|
|
249
|
+
placed_per_level = {}
|
|
250
|
+
|
|
251
|
+
for candidate in self.__collectCandidates__(parent):
|
|
252
|
+
level_index = candidate["level_index"]
|
|
253
|
+
if self.labelMaxPerLevel is not None:
|
|
254
|
+
if placed_per_level.get(level_index, 0) >= self.labelMaxPerLevel:
|
|
255
|
+
continue
|
|
256
|
+
|
|
257
|
+
angle = contour_label_angle(candidate["polyline"], candidate["index"])
|
|
258
|
+
text = Text(
|
|
259
|
+
candidate["label_text"],
|
|
260
|
+
int(candidate["point"][0]),
|
|
261
|
+
int(candidate["point"][1]),
|
|
262
|
+
fontSize=fontSize,
|
|
263
|
+
color=self.labelColor,
|
|
264
|
+
rotate=int(angle),
|
|
265
|
+
anchor_x='center',
|
|
266
|
+
anchor_y='center',
|
|
267
|
+
)
|
|
268
|
+
bbox = text.getBoundingBox()
|
|
269
|
+
|
|
270
|
+
if any(
|
|
271
|
+
bbox_overlaps(bbox, placed_bbox, self.labelCollisionPadding)
|
|
272
|
+
for placed_bbox in placed_bboxes
|
|
273
|
+
):
|
|
274
|
+
continue
|
|
275
|
+
|
|
276
|
+
text.batch = self.batch
|
|
277
|
+
self.batch.add(text)
|
|
278
|
+
placed_bboxes.append(bbox)
|
|
279
|
+
label_bboxes.append(bbox)
|
|
280
|
+
placed_per_level[level_index] = placed_per_level.get(level_index, 0) + 1
|
|
257
281
|
|
|
258
282
|
if not label_bboxes:
|
|
259
283
|
return
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-oblique.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-roman.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.bright-semibold.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bold.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bolditalic.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-italic.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.concrete-roman.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-bold.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-medium.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-oblique.ttf
RENAMED
|
File without changes
|
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-bolditalic.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-italic.ttf
RENAMED
|
File without changes
|
{kaxe-1.5.5.dev0 → kaxe-1.5.6}/src/kaxe/resources/computer-modern-family/cmu.serif-roman.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|