draftwright 0.2.1__tar.gz → 0.2.3__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.
- {draftwright-0.2.1 → draftwright-0.2.3}/CHANGELOG.md +72 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/PKG-INFO +1 -1
- {draftwright-0.2.1 → draftwright-0.2.3}/pyproject.toml +1 -1
- draftwright-0.2.3/src/draftwright/__init__.py +103 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/_core.py +7 -50
- draftwright-0.2.3/src/draftwright/annotations/_common.py +401 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/annotations/from_model.py +292 -109
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/annotations/holes.py +436 -205
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/annotations/orchestrator.py +172 -101
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/annotations/sections.py +121 -24
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/cli.py +6 -2
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/drawing.py +58 -31
- draftwright-0.2.3/src/draftwright/layout.py +676 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/linting/coverage.py +15 -0
- draftwright-0.2.3/tests/layout_snapshots/box.json +116 -0
- draftwright-0.2.3/tests/layout_snapshots/bracket.json +388 -0
- draftwright-0.2.3/tests/layout_snapshots/drive_screw_x.json +155 -0
- draftwright-0.2.3/tests/layout_snapshots/dshape.json +201 -0
- draftwright-0.2.3/tests/layout_snapshots/flange.json +287 -0
- draftwright-0.2.3/tests/layout_snapshots/plate_holes.json +258 -0
- draftwright-0.2.3/tests/layout_snapshots/side_drilled.json +183 -0
- draftwright-0.2.3/tests/layout_snapshots/slotted.json +170 -0
- draftwright-0.2.3/tests/layout_snapshots/turned_shaft.json +196 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_layout.py +176 -4
- draftwright-0.2.3/tests/test_layout_cleanliness.py +179 -0
- draftwright-0.2.3/tests/test_layout_property.py +201 -0
- draftwright-0.2.3/tests/test_layout_snapshot.py +213 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_make_drawing.py +283 -106
- draftwright-0.2.3/tests/test_render_seam.py +200 -0
- draftwright-0.2.3/tests/test_strip_layout.py +673 -0
- draftwright-0.2.1/src/draftwright/__init__.py +0 -62
- draftwright-0.2.1/src/draftwright/annotations/_common.py +0 -51
- draftwright-0.2.1/src/draftwright/layout.py +0 -317
- draftwright-0.2.1/tests/test_render_seam.py +0 -63
- {draftwright-0.2.1 → draftwright-0.2.3}/.gitignore +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/LICENSE +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/README.md +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/skills/SKILL.md +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/analysis.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/annotate.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/builder.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/export.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/features.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/linting/__init__.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/linting/issues.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/linting/structural.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/make_drawing.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/model/__init__.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/model/detect.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/model/ir.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/model/planner.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/pmi.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/projection.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/recognition/__init__.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/recognition/_features.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/recognition/levels.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/recognition/slots.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/recognition/turned.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/registry.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/repair.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/src/draftwright/sheet.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_e2e_slice.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_e2e_standards.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_lint_structural.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_linting.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_part_model.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_pmi.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_recognition.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_registry.py +0 -0
- {draftwright-0.2.1 → draftwright-0.2.3}/tests/test_turned_steps.py +0 -0
|
@@ -2,6 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v0.2.3 — 2026-07-03
|
|
6
|
+
|
|
7
|
+
A large patch release: the **annotation-placement engine was rebuilt** as a
|
|
8
|
+
collect-then-solve *boundary-labeling* stage (ADR 0009). Placement is now
|
|
9
|
+
deterministic and minimises total leader length, and the recurring class of
|
|
10
|
+
overlaps where a label was drawn on top of an "invisible" occupant — a leader
|
|
11
|
+
shaft, a witness/extension line, the section hatch — is removed by construction.
|
|
12
|
+
Drawing output changes for many turned, cross-drilled, and multi-feature parts.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **Every annotation in a view's margin is now placed by one collect-then-solve
|
|
17
|
+
pass** (ADR 0009, #317–#323). Dimensions, hole callouts, turned-diameter
|
|
18
|
+
leaders, and the section hatch share a single occupancy model instead of several
|
|
19
|
+
independent passes each blind to the others. When a strip is over capacity it now
|
|
20
|
+
drops the *lowest-priority* annotation (smallest bore first) rather than whichever
|
|
21
|
+
pass happened to run last. The legacy strip cursor is retired.
|
|
22
|
+
- **Leader placement minimises total leader length, deterministically** (P4,
|
|
23
|
+
#318). A per-strip solve places each label at the shortest-leader position that
|
|
24
|
+
keeps the labels in order and clear of keep-out rows (a view centre-line, a
|
|
25
|
+
dimension's extension line); central/coaxial callouts are anchored to the
|
|
26
|
+
view-centre row. Output is reproducible across platforms and Python versions.
|
|
27
|
+
- **`scipy` is no longer a dependency** — the leader solve is a small deterministic
|
|
28
|
+
algorithm (weighted-median isotonic regression), not a linear program.
|
|
29
|
+
- **Output changes** for turned, cross-drilled, and multi-feature parts whose
|
|
30
|
+
margin annotations are now positioned by the unified solver.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **A PMI bore-diameter dimension spans the bore radius, not the full diameter**
|
|
35
|
+
(#360). A `pmi="annotate"` diameter callout drew its witness lines at ±diameter
|
|
36
|
+
from the centre — twice too wide, missing the bore edges.
|
|
37
|
+
- **A bore coaxial with a rotational part's turning axis is no longer
|
|
38
|
+
over-dimensioned** (#309). It carried a redundant offset *and* height location
|
|
39
|
+
dimension even though its centre mark already locates it.
|
|
40
|
+
- **A dropped turned step-length chain is no longer silent** (#362). When a turned
|
|
41
|
+
head's shoulders are too crowded to dimension, the drop is now reported
|
|
42
|
+
(`step_dim_dropped`) instead of vanishing with no lint or on-sheet signal.
|
|
43
|
+
- **A diameter callout can no longer overprint a bore callout's leader shaft**
|
|
44
|
+
(#358). The turned-diameter column now avoids the *full* footprint of existing
|
|
45
|
+
annotations, not just their text boxes.
|
|
46
|
+
- **The balloon ring hugs its dimensions on a cramped sheet** (#349) — its band
|
|
47
|
+
depth is clamped to the drawable area.
|
|
48
|
+
- **Dimension detection is robust to `SafeDimension`** (#335/#349) — the corridor
|
|
49
|
+
and balloon-ring filters test the dimension *type*, not a class-name string, so a
|
|
50
|
+
future dimension subclass can't slip through.
|
|
51
|
+
|
|
52
|
+
## v0.2.2 — 2026-06-30
|
|
53
|
+
|
|
54
|
+
A patch release of turned-part dimension-placement fixes and a CLI start-up
|
|
55
|
+
speed-up. Drawing output changes for the affected turned/cross-drilled parts.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- **A coaxial bore callout on a *stepped* turned shaft is now lifted off the round
|
|
60
|
+
view's centre axis** (#305). The earlier fix only triggered for a uniform
|
|
61
|
+
(`is_rotational`) cylinder; a stepped shaft (e.g. the gramel GRM-03 drive screw)
|
|
62
|
+
has a turned step profile but isn't classified rotational, so its `⌀… ↓…` bore
|
|
63
|
+
callout was still leadered straight along the centreline, with the centre mark
|
|
64
|
+
running through the text. The lift now also fires for a turned-profile part.
|
|
65
|
+
- **A side-drilled hole's location dimension now stacks *inside* the overall
|
|
66
|
+
envelope dimension** (ISO order — overall dim outermost, feature/location dims
|
|
67
|
+
nearer the view). It was placed *outside* the envelope, which forced the shorter
|
|
68
|
+
location dim's arrowheads to flip outward and clash (seen on GRM-01 and GRM-02).
|
|
69
|
+
The mandatory overall dimension is still guaranteed placement.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- **CLI shell completion and `--help` are fast again** (#313). The Typer CLI and
|
|
74
|
+
the heavy CAD engine are now imported lazily, so tab-completion and `--help` no
|
|
75
|
+
longer pay a ~6 s engine-import cost; a real drawing run is unaffected.
|
|
76
|
+
|
|
5
77
|
## v0.2.1 — 2026-06-30
|
|
6
78
|
|
|
7
79
|
A patch release focused on **turned-part dimensioning legibility**: crowded
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""draftwright — automated technical-drawing generation for build123d.
|
|
2
|
+
|
|
3
|
+
Takes a build123d solid and produces a fully-annotated multi-view technical
|
|
4
|
+
drawing (orthographic views, dimensions, section A–A, title block) ready for
|
|
5
|
+
DXF/SVG export::
|
|
6
|
+
|
|
7
|
+
from draftwright import make_drawing
|
|
8
|
+
make_drawing(my_part, out="drawing")
|
|
9
|
+
|
|
10
|
+
Requires build123d-drafting-helpers for annotation primitives.
|
|
11
|
+
Licensed under the GNU Affero General Public License v3 (AGPL-3.0).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import importlib as _importlib
|
|
15
|
+
import sys as _sys
|
|
16
|
+
import types as _types
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
18
|
+
|
|
19
|
+
# Public API resolved lazily (PEP 562): `import draftwright` — and, crucially,
|
|
20
|
+
# `import draftwright.cli` (which runs this __init__ first) — must NOT eagerly
|
|
21
|
+
# pull in the engine. The engine drags build123d/OCP, ~5 s of CAD-kernel import.
|
|
22
|
+
# The CLI's shell completion, --help and --version import this package but touch
|
|
23
|
+
# none of these names, so they stay sub-second instead of paying for the kernel
|
|
24
|
+
# on every TAB press (#313). Each name maps to the submodule that provides it.
|
|
25
|
+
_LAZY = {
|
|
26
|
+
"analyse_face_levels": "draftwright.analysis",
|
|
27
|
+
"dedup_diams": "draftwright.analysis",
|
|
28
|
+
"build_drawing": "draftwright.builder",
|
|
29
|
+
"generate_script": "draftwright.builder",
|
|
30
|
+
"make_drawing": "draftwright.builder",
|
|
31
|
+
"Drawing": "draftwright.drawing",
|
|
32
|
+
"FeatureInfo": "draftwright.drawing",
|
|
33
|
+
"fix_svg_page_size": "draftwright.export",
|
|
34
|
+
"lint_feature_coverage": "draftwright.linting",
|
|
35
|
+
"PmiRecord": "draftwright.pmi",
|
|
36
|
+
"extract_pmi": "draftwright.pmi",
|
|
37
|
+
"choose_scale": "draftwright.sheet",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _resolve(name):
|
|
42
|
+
"""Import the providing submodule and cache the public object on the package."""
|
|
43
|
+
value = getattr(_importlib.import_module(_LAZY[name]), name)
|
|
44
|
+
_types.ModuleType.__setattr__(_sys.modules[__name__], name, value)
|
|
45
|
+
return value
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class _DraftwrightModule(_types.ModuleType):
|
|
49
|
+
def __getattr__(self, name):
|
|
50
|
+
# PEP 562 miss handler: resolve a public name on first access.
|
|
51
|
+
if name in _LAZY:
|
|
52
|
+
return _resolve(name)
|
|
53
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
54
|
+
|
|
55
|
+
def __getattribute__(self, name):
|
|
56
|
+
# `draftwright.make_drawing` must be the FUNCTION even after the compat
|
|
57
|
+
# SUBMODULE of the same name is imported and shadows it as a package
|
|
58
|
+
# attribute (importing draftwright.make_drawing binds the module here).
|
|
59
|
+
if name == "make_drawing":
|
|
60
|
+
namespace = _types.ModuleType.__getattribute__(self, "__dict__")
|
|
61
|
+
value = namespace.get("make_drawing")
|
|
62
|
+
if (
|
|
63
|
+
isinstance(value, _types.ModuleType)
|
|
64
|
+
and value.__name__ == "draftwright.make_drawing"
|
|
65
|
+
):
|
|
66
|
+
return _resolve("make_drawing")
|
|
67
|
+
return _types.ModuleType.__getattribute__(self, name)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
_sys.modules[__name__].__class__ = _DraftwrightModule
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if TYPE_CHECKING: # static analysers / IDEs — no runtime import, no kernel cost
|
|
74
|
+
from draftwright.analysis import analyse_face_levels, dedup_diams
|
|
75
|
+
from draftwright.builder import build_drawing, generate_script, make_drawing
|
|
76
|
+
from draftwright.drawing import Drawing, FeatureInfo
|
|
77
|
+
from draftwright.export import fix_svg_page_size
|
|
78
|
+
from draftwright.linting import lint_feature_coverage
|
|
79
|
+
from draftwright.pmi import PmiRecord, extract_pmi
|
|
80
|
+
from draftwright.sheet import choose_scale
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def __dir__():
|
|
84
|
+
# Surface the lazy public names (not in __dict__ until first accessed)
|
|
85
|
+
# *alongside* the normal module contents — dunders, imported submodules — so
|
|
86
|
+
# introspection / REPL completion sees the full surface, not a subset.
|
|
87
|
+
return sorted(set(globals()) | set(__all__))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
__all__ = [
|
|
91
|
+
"Drawing",
|
|
92
|
+
"FeatureInfo",
|
|
93
|
+
"PmiRecord",
|
|
94
|
+
"analyse_face_levels",
|
|
95
|
+
"build_drawing",
|
|
96
|
+
"choose_scale",
|
|
97
|
+
"dedup_diams",
|
|
98
|
+
"extract_pmi",
|
|
99
|
+
"fix_svg_page_size",
|
|
100
|
+
"generate_script",
|
|
101
|
+
"lint_feature_coverage",
|
|
102
|
+
"make_drawing",
|
|
103
|
+
]
|
|
@@ -14,7 +14,7 @@ import functools
|
|
|
14
14
|
import logging
|
|
15
15
|
import re
|
|
16
16
|
from collections.abc import Callable
|
|
17
|
-
from dataclasses import dataclass
|
|
17
|
+
from dataclasses import dataclass
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from types import SimpleNamespace
|
|
20
20
|
from typing import TYPE_CHECKING
|
|
@@ -166,16 +166,17 @@ def _dim(p1, p2, side, distance, draft, **kwargs):
|
|
|
166
166
|
class Strip:
|
|
167
167
|
"""A one-dimensional annotation band adjacent to an orthographic view.
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
:
|
|
171
|
-
|
|
169
|
+
A plain geometry record: the collect-then-solve placers (ADR 0009) read its
|
|
170
|
+
bounds (:func:`~draftwright.annotations._common.strip_free_span`) and carve
|
|
171
|
+
around the placed annotations. The mutable ``allocate``/``peek`` cursor was
|
|
172
|
+
retired once every placer moved to the carve (#150).
|
|
172
173
|
|
|
173
174
|
Attributes:
|
|
174
175
|
anchor: Page coordinate of the view edge this strip starts from.
|
|
175
176
|
outer_limit: Page coordinate at which the strip ends (page margin,
|
|
176
177
|
neighbouring view, or title-block boundary).
|
|
177
|
-
direction: ``+1`` —
|
|
178
|
-
``-1`` —
|
|
178
|
+
direction: ``+1`` — stacks away from anchor (right/above);
|
|
179
|
+
``-1`` — stacks back toward smaller coords (left/below).
|
|
179
180
|
gap: Clearance between the view edge and the first annotation.
|
|
180
181
|
spacing: Clearance between successive annotations.
|
|
181
182
|
"""
|
|
@@ -185,56 +186,12 @@ class Strip:
|
|
|
185
186
|
direction: float = 1.0
|
|
186
187
|
gap: float = 8.0
|
|
187
188
|
spacing: float = 4.0
|
|
188
|
-
_cursor: float = field(init=False, compare=False, repr=False)
|
|
189
|
-
|
|
190
|
-
def __post_init__(self):
|
|
191
|
-
self._cursor = self.anchor + self.direction * self.gap
|
|
192
|
-
|
|
193
|
-
# ------------------------------------------------------------------
|
|
194
|
-
# Public API
|
|
195
189
|
|
|
196
190
|
@property
|
|
197
191
|
def available(self) -> float:
|
|
198
192
|
"""Total space available in this strip (mm)."""
|
|
199
193
|
return abs(self.outer_limit - self.anchor)
|
|
200
194
|
|
|
201
|
-
@property
|
|
202
|
-
def depth_used(self) -> float:
|
|
203
|
-
"""How far the cursor has advanced from the anchor (mm)."""
|
|
204
|
-
return abs(self._cursor - self.anchor)
|
|
205
|
-
|
|
206
|
-
def peek(self, size: float) -> float | None:
|
|
207
|
-
"""Return what ``allocate(size)`` would return without advancing the cursor."""
|
|
208
|
-
if self.direction == 1:
|
|
209
|
-
start = self._cursor
|
|
210
|
-
return start if (start + size) <= self.outer_limit else None
|
|
211
|
-
else:
|
|
212
|
-
end = self._cursor
|
|
213
|
-
return end if (end - size) >= self.outer_limit else None
|
|
214
|
-
|
|
215
|
-
def allocate(self, size: float) -> float | None:
|
|
216
|
-
"""Reserve *size* mm; return the near-edge page coordinate, or ``None`` if full.
|
|
217
|
-
|
|
218
|
-
The returned value is the page coordinate of the annotation's
|
|
219
|
-
dimension line (or leader elbow). Convert to a relative offset with::
|
|
220
|
-
|
|
221
|
-
distance = abs(page_coord - strip.anchor)
|
|
222
|
-
"""
|
|
223
|
-
if self.direction == 1:
|
|
224
|
-
start = self._cursor
|
|
225
|
-
end = start + size
|
|
226
|
-
if end > self.outer_limit:
|
|
227
|
-
return None
|
|
228
|
-
self._cursor = end + self.spacing
|
|
229
|
-
return start
|
|
230
|
-
else:
|
|
231
|
-
end = self._cursor
|
|
232
|
-
start = end - size
|
|
233
|
-
if start < self.outer_limit:
|
|
234
|
-
return None
|
|
235
|
-
self._cursor = start - self.spacing
|
|
236
|
-
return end
|
|
237
|
-
|
|
238
195
|
|
|
239
196
|
@dataclass
|
|
240
197
|
class ViewZones:
|