Skip to content

Commit bf4b6ce

Browse files
committed
.
1 parent d6b5945 commit bf4b6ce

File tree

8 files changed

+187
-114
lines changed

8 files changed

+187
-114
lines changed

api/alignment.py

+90-33
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,156 @@
1-
# + tags=["hide_inp"]
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# cell_markers: '"""'
5+
# cell_metadata_filter: tags,title,-all
6+
# formats: py:percent
7+
# text_representation:
8+
# extension: .py
9+
# format_name: percent
10+
# format_version: '1.3'
11+
# jupytext_version: 1.16.4
12+
# ---
13+
14+
# %% tags=["hide_inp"]
215
from chalk.core import BaseDiagram
316
from chalk import *
4-
# -
517

618

7-
# Each diagram has an origin and an envelope.
8-
# Manipulating the position of the diagram with respect to its origin and envelope allows for precise control of the layout.
9-
# Note that the Chalk API is immutable and always returns a new ``Diagram`` object.
19+
# %% [markdown]
20+
"""
21+
Each diagram has an origin and an envelope.
22+
Manipulating the position of the diagram with respect to its origin and envelope allows for precise control of the layout.
23+
Note that the Chalk API is immutable and always returns a new ``Diagram`` object.
24+
"""
1025

11-
# ### Diagram.show_origin
26+
# %% [markdown]
27+
"""
28+
### Diagram.show_origin
29+
"""
1230

13-
# + tags=["hide_inp"]
31+
# %% tags=["hide_inp"]
1432
help(BaseDiagram.show_origin)
15-
# -
1633

17-
#
34+
# %% [markdown]
35+
"""
1836
19-
triangle(1).show_origin()
37+
"""
38+
39+
# %%
40+
d = triangle(1).show_origin()
41+
from IPython.display import HTML, Image
42+
d.render("test.png")
43+
Image("test.png")
2044

2145

22-
triangle(1).show_origin().render_svg("/tmp/test.svg")
46+
# %%
47+
triangle(1).show_origin()
2348

24-
# ### Diagram.show_envelope
49+
# %% [markdown]
50+
"""
51+
### Diagram.show_envelope
52+
"""
2553

26-
# + tags=["hide_inp"]
54+
# %% tags=["hide_inp"]
2755
help(BaseDiagram.show_envelope)
28-
# -
2956

57+
# %% Cell 2
3058
rectangle(1, 1).show_envelope()
3159

3260

61+
# %%
3362
triangle(1).show_envelope()
3463

3564

65+
# %%
3666
rectangle(1, 1).show_beside(triangle(1), unit_x)
3767

3868

69+
# %%
3970
(rectangle(1, 1) | triangle(1)).pad(1.4)
4071

4172

73+
# %%
4274
arc(1, 0, 90)
4375

44-
# ### Diagram.align_*
76+
# %% [markdown]
77+
"""
78+
### Diagram.align_*
79+
"""
4580

46-
# + tags=["hide_inp"]
81+
# %% tags=["hide_inp"]
4782
help(BaseDiagram.align_t)
48-
# -
4983

50-
#
84+
# %% [markdown]
85+
"""
5186
52-
triangle(1).align_t().show_origin()
87+
"""
5388

89+
# %%
90+
triangle(1).align_t().show_origin()
5491

92+
# %%
5593

94+
# %%
5695
triangle(1).align_t().show_beside(rectangle(1, 1).align_b(), unit_x)
5796

5897

59-
# + tags=["hide_inp"]
98+
# %% tags=["hide_inp"]
6099
help(BaseDiagram.align_r)
61-
# -
62100

63-
# ### Diagram.center_xy
101+
# %% [markdown]
102+
"""
103+
### Diagram.center_xy
104+
"""
64105

65-
# + tags=["hide_inp"]
106+
# %% tags=["hide_inp"]
66107
help(BaseDiagram.center_xy)
67-
# -
68108

69-
#
109+
# %% [markdown]
110+
"""
111+
112+
"""
70113

114+
# %%
71115
triangle(1).center_xy().show_envelope().show_origin()
72116

73117

74-
# ### Diagram.pad_*
118+
# %% [markdown]
119+
"""
120+
### Diagram.pad_*
121+
"""
75122

76-
# + tags=["hide_inp"]
123+
# %% tags=["hide_inp"]
77124
help(BaseDiagram.pad)
78-
# -
79125

80126

81-
#
127+
# %% [markdown]
128+
"""
82129
130+
"""
131+
132+
# %%
83133
triangle(1).pad(1.5).show_envelope().show_origin()
84134

85135

86-
# ### Diagram.with_envelope
136+
# %% [markdown]
137+
"""
138+
### Diagram.with_envelope
139+
"""
87140

88-
# + tags=["hide_inp"]
141+
# %% tags=["hide_inp"]
89142
help(BaseDiagram.with_envelope)
90-
# -
91143

92144

93-
#
145+
# %% [markdown]
146+
"""
147+
148+
"""
94149

95150

151+
# %%
96152
(rectangle(1, 1) + triangle(0.5)) | rectangle(1, 1)
97153

98154

155+
# %%
99156
(rectangle(1, 1) + triangle(0.5)).with_envelope(triangle(0.5)) | rectangle(1, 1).fill_color("red")

chalk/backend/svg.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ def write_style(d: Dict[str, Any]) -> Dict[str, str]:
5454
def render_svg_patches(patches: List[Patch], animate:bool=False, time_steps:int=0) -> str:
5555
if animate:
5656
out = ""
57-
patches = [chalk.backend.patch.order_patches(patches, (step,))
57+
new_patches = [chalk.backend.patch.order_patches(patches, (step,))
5858
for step in range(time_steps)]
59-
for v in zip(*patches):
59+
for v in zip(*new_patches):
6060
out += "\n\n <path>\n"
6161
lines = []
6262
css = {}
@@ -99,6 +99,7 @@ def render_svg_patches(patches: List[Patch], animate:bool=False, time_steps:int=
9999
<path d="{inner}" />
100100
</g>"""
101101
return out
102+
102103
def patches_to_file(
103104
patches: List[Patch], path: str, height: tx.IntLike,
104105
width: tx.IntLike,

chalk/combinators.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import chalk.transform as tx
44
from chalk.monoid import associative_reduce
55
from chalk.path import Path
6-
from chalk.transform import Floating, Scalars, V2_t
6+
from chalk.transform import Floating, V2_t
77
from chalk.types import (
88
BatchDiagram,
99
BroadDiagram,
@@ -12,8 +12,6 @@
1212
ExtraDiagram,
1313
)
1414

15-
# Functions mirroring Diagrams.Combinators and Diagrams.2d.Combinators
16-
1715

1816
def with_envelope(self: Diagram, other: Diagram) -> Diagram:
1917
"""
@@ -25,7 +23,6 @@ def with_envelope(self: Diagram, other: Diagram) -> Diagram:
2523

2624
def pad(self: Diagram, extra: Floating) -> Diagram:
2725
"""Scale outward directed padding for a diagram.
28-
2926
Be careful using this if your diagram is not centered.
3027
"""
3128
envelope = self.get_envelope()
@@ -108,7 +105,6 @@ def call_scan(diagram: Diagram) -> Diagram:
108105
t = v * off[..., None, None]
109106
return diagram.translate_by(t)
110107

111-
# call_scan = tx.multi_vmap(call_scan, axis) # type: ignore
112108
return call_scan(diagram).compose_axis()
113109

114110

chalk/core.py

+9
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,15 @@ def _repr_svg_(self) -> str:
218218
os.unlink(f.name)
219219
return svg
220220

221+
def _repr_png_(self) -> str:
222+
global Svg_Height, Svg_Draw_Height
223+
f = tempfile.NamedTemporaryFile(delete=False)
224+
self.render(f.name, height=Svg_Height, draw_height=Svg_Draw_Height)
225+
f.close()
226+
png = open(f.name).read()
227+
os.unlink(f.name)
228+
return png
229+
221230
def _repr_html_(self) -> str | tuple[str, Any]:
222231
"""Returns a rich HTML representation of an object."""
223232
return self._repr_svg_()

chalk/envelope.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from dataclasses import dataclass
44
from functools import partial
5-
from typing import TYPE_CHECKING, Iterable, Optional, Tuple
5+
from typing import TYPE_CHECKING, Iterable, Optional, Tuple
66

77
import chalk.transform as tx
88
from chalk.monoid import Monoid
@@ -77,7 +77,7 @@ def env(transform: tx.Affine, angles: tx.Angles, d: tx.V2_tC) -> tx.Array:
7777
class Envelope(Transformable, Monoid, Batchable):
7878
segment: BatchSegment
7979

80-
def __call__(self, direction: V2_t) -> tx.Array:
80+
def __call__(self: BatchEnvelope, direction: V2_t) -> Scalars:
8181
return env(*self.segment.tuple(), direction)
8282

8383
def __add__(self: BatchEnvelope, other: BatchEnvelope) -> BatchEnvelope:
@@ -88,28 +88,34 @@ def __add__(self: BatchEnvelope, other: BatchEnvelope) -> BatchEnvelope:
8888
)
8989

9090
@property
91-
def center(self) -> P2_t:
91+
def center(self: BatchEnvelope) -> P2_t:
9292
d = self(Envelope.all_dir)
9393
return P2(
9494
(-d[1] + d[0]) / 2,
9595
(-d[3] + d[2]) / 2,
9696
)
9797

9898
@property
99-
def width(self) -> Scalars:
99+
def width(self: BatchEnvelope) -> Scalars:
100100
d1 = self(Envelope.all_dir[:2])
101101
return tx.np.asarray(d1[0] + d1[1])
102102

103103
@property
104-
def height(self) -> Scalars:
104+
def height(self: BatchEnvelope) -> Scalars:
105105
d1 = self(Envelope.all_dir[2:])
106106
return tx.np.asarray(d1[0] + d1[1])
107107

108-
def envelope_v(self, v: V2_t) -> V2_t:
108+
def size(self: BatchEnvelope) -> Tuple[Scalars, Scalars]:
109+
d = self(Envelope.all_dir)
110+
width = tx.np.asarray(d[0] + d[1])
111+
height = tx.np.asarray(d[2] + d[3])
112+
return width, height
113+
114+
115+
def envelope_v(self: BatchEnvelope, v: V2_t) -> V2_t:
109116
v = tx.norm(v)
110117
d = self(v)
111118
return tx.scale_vec(v, d)
112-
113119
@staticmethod
114120
def from_bounding_box(box: BoundingBox, d: V2_t) -> Scalars:
115121
v = box.rotate_rad(tx.rad(d)).br[:, 0, 0]
@@ -176,4 +182,4 @@ def get_envelope(self: Diagram, t: Optional[Affine] = None) -> Envelope:
176182
assert segment.shape[:len(self.shape)] == self.shape, f"{segment.transform.shape} {self.shape}"
177183
return Envelope(segment)
178184

179-
BatchEnvelope = Batched[Envelope, "*#B"]
185+
BatchEnvelope = Batched[Envelope, "*#B"]

chalk/layout.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ def animate(
2727
) -> Tuple[List[Patch], tx.IntLike, tx.IntLike]:
2828
return layout(self, height, width, draw_height)
2929

30-
3130
def layout(
3231
self: BatchDiagram,
3332
height: tx.IntLike = 128,
@@ -45,19 +44,21 @@ def layout(
4544

4645
pad = tx.np.array(0.05)
4746

47+
envelope_width, envelope_height = envelope.size()
48+
4849
# infer width to preserve aspect ratio
4950
if width is None:
50-
width = tx.np.round(height * envelope.width / envelope.height).astype(
51+
width = tx.np.round(height * envelope_width / envelope_height).astype(
5152
int
5253
)
5354
else:
5455
width = width
5556
assert width is not None
5657
# determine scale to fit the largest axis in the target frame size
5758
α = tx.np.where(
58-
envelope.width - width <= envelope.height - height,
59-
height / ((1 + pad) * envelope.height),
60-
width / ((1 + pad) * envelope.width),
59+
envelope_width - width <= envelope_height - height,
60+
height / ((1 + pad) * envelope_height),
61+
width / ((1 + pad) * envelope_width),
6162
)
6263
s = self.scale(α).center_xy().pad(1 + pad)
6364
e = s.get_envelope()

chalk/shapes.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import chalk.trail as Trail
44
import chalk.transform as tx
5-
from chalk.path import from_list_of_tuples, from_text # noqa: F401
5+
from chalk.path import from_list_of_tuples, Path, from_text # noqa: F401
66
from chalk.trail import arc_seg, arc_seg_angle # noqa: F401
77
from chalk.transform import P2, P2_t
88
from chalk.types import BatchDiagram, Diagram
@@ -52,9 +52,12 @@ def line(from_: Tuple[tx.Floating, tx.Floating], to: Tuple[tx.Floating, tx.Float
5252
return make_path([from_, to])
5353

5454
def make_path(
55-
segments: List[Tuple[tx.Floating, tx.Floating]], closed: bool = False
55+
segments: Union[List[Tuple[tx.Floating, tx.Floating]], tx.P2_t], closed: bool = False
5656
) -> Diagram:
57-
p = from_list_of_tuples(segments, closed).stroke()
57+
if isinstance(segments, (list, tuple)):
58+
p = from_list_of_tuples(segments, closed).stroke()
59+
else:
60+
p = Path.from_array(segments, closed).stroke()
5861
return p
5962

6063

0 commit comments

Comments
 (0)