Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
srush committed Aug 28, 2024
1 parent d6b5945 commit bf4b6ce
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 114 deletions.
123 changes: 90 additions & 33 deletions api/alignment.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,156 @@
# + tags=["hide_inp"]
# ---
# jupyter:
# jupytext:
# cell_markers: '"""'
# cell_metadata_filter: tags,title,-all
# formats: py:percent
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.16.4
# ---

# %% tags=["hide_inp"]
from chalk.core import BaseDiagram
from chalk import *
# -


# Each diagram has an origin and an envelope.
# Manipulating the position of the diagram with respect to its origin and envelope allows for precise control of the layout.
# Note that the Chalk API is immutable and always returns a new ``Diagram`` object.
# %% [markdown]
"""
Each diagram has an origin and an envelope.
Manipulating the position of the diagram with respect to its origin and envelope allows for precise control of the layout.
Note that the Chalk API is immutable and always returns a new ``Diagram`` object.
"""

# ### Diagram.show_origin
# %% [markdown]
"""
### Diagram.show_origin
"""

# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.show_origin)
# -

#
# %% [markdown]
"""
triangle(1).show_origin()
"""

# %%
d = triangle(1).show_origin()
from IPython.display import HTML, Image
d.render("test.png")
Image("test.png")


triangle(1).show_origin().render_svg("/tmp/test.svg")
# %%
triangle(1).show_origin()

# ### Diagram.show_envelope
# %% [markdown]
"""
### Diagram.show_envelope
"""

# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.show_envelope)
# -

# %% Cell 2
rectangle(1, 1).show_envelope()


# %%
triangle(1).show_envelope()


# %%
rectangle(1, 1).show_beside(triangle(1), unit_x)


# %%
(rectangle(1, 1) | triangle(1)).pad(1.4)


# %%
arc(1, 0, 90)

# ### Diagram.align_*
# %% [markdown]
"""
### Diagram.align_*
"""

# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.align_t)
# -

#
# %% [markdown]
"""
triangle(1).align_t().show_origin()
"""

# %%
triangle(1).align_t().show_origin()

# %%

# %%
triangle(1).align_t().show_beside(rectangle(1, 1).align_b(), unit_x)


# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.align_r)
# -

# ### Diagram.center_xy
# %% [markdown]
"""
### Diagram.center_xy
"""

# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.center_xy)
# -

#
# %% [markdown]
"""
"""

# %%
triangle(1).center_xy().show_envelope().show_origin()


# ### Diagram.pad_*
# %% [markdown]
"""
### Diagram.pad_*
"""

# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.pad)
# -


#
# %% [markdown]
"""
"""

# %%
triangle(1).pad(1.5).show_envelope().show_origin()


# ### Diagram.with_envelope
# %% [markdown]
"""
### Diagram.with_envelope
"""

# + tags=["hide_inp"]
# %% tags=["hide_inp"]
help(BaseDiagram.with_envelope)
# -


#
# %% [markdown]
"""
"""


# %%
(rectangle(1, 1) + triangle(0.5)) | rectangle(1, 1)


# %%
(rectangle(1, 1) + triangle(0.5)).with_envelope(triangle(0.5)) | rectangle(1, 1).fill_color("red")
5 changes: 3 additions & 2 deletions chalk/backend/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ def write_style(d: Dict[str, Any]) -> Dict[str, str]:
def render_svg_patches(patches: List[Patch], animate:bool=False, time_steps:int=0) -> str:
if animate:
out = ""
patches = [chalk.backend.patch.order_patches(patches, (step,))
new_patches = [chalk.backend.patch.order_patches(patches, (step,))
for step in range(time_steps)]
for v in zip(*patches):
for v in zip(*new_patches):
out += "\n\n <path>\n"
lines = []
css = {}
Expand Down Expand Up @@ -99,6 +99,7 @@ def render_svg_patches(patches: List[Patch], animate:bool=False, time_steps:int=
<path d="{inner}" />
</g>"""
return out

def patches_to_file(
patches: List[Patch], path: str, height: tx.IntLike,
width: tx.IntLike,
Expand Down
6 changes: 1 addition & 5 deletions chalk/combinators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import chalk.transform as tx
from chalk.monoid import associative_reduce
from chalk.path import Path
from chalk.transform import Floating, Scalars, V2_t
from chalk.transform import Floating, V2_t
from chalk.types import (
BatchDiagram,
BroadDiagram,
Expand All @@ -12,8 +12,6 @@
ExtraDiagram,
)

# Functions mirroring Diagrams.Combinators and Diagrams.2d.Combinators


def with_envelope(self: Diagram, other: Diagram) -> Diagram:
"""
Expand All @@ -25,7 +23,6 @@ def with_envelope(self: Diagram, other: Diagram) -> Diagram:

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

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


Expand Down
9 changes: 9 additions & 0 deletions chalk/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,15 @@ def _repr_svg_(self) -> str:
os.unlink(f.name)
return svg

def _repr_png_(self) -> str:
global Svg_Height, Svg_Draw_Height
f = tempfile.NamedTemporaryFile(delete=False)
self.render(f.name, height=Svg_Height, draw_height=Svg_Draw_Height)
f.close()
png = open(f.name).read()
os.unlink(f.name)
return png

def _repr_html_(self) -> str | tuple[str, Any]:
"""Returns a rich HTML representation of an object."""
return self._repr_svg_()
Expand Down
22 changes: 14 additions & 8 deletions chalk/envelope.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from dataclasses import dataclass
from functools import partial
from typing import TYPE_CHECKING, Iterable, Optional, Tuple
from typing import TYPE_CHECKING, Iterable, Optional, Tuple

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

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

def __add__(self: BatchEnvelope, other: BatchEnvelope) -> BatchEnvelope:
Expand All @@ -88,28 +88,34 @@ def __add__(self: BatchEnvelope, other: BatchEnvelope) -> BatchEnvelope:
)

@property
def center(self) -> P2_t:
def center(self: BatchEnvelope) -> P2_t:
d = self(Envelope.all_dir)
return P2(
(-d[1] + d[0]) / 2,
(-d[3] + d[2]) / 2,
)

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

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

def envelope_v(self, v: V2_t) -> V2_t:
def size(self: BatchEnvelope) -> Tuple[Scalars, Scalars]:
d = self(Envelope.all_dir)
width = tx.np.asarray(d[0] + d[1])
height = tx.np.asarray(d[2] + d[3])
return width, height


def envelope_v(self: BatchEnvelope, v: V2_t) -> V2_t:
v = tx.norm(v)
d = self(v)
return tx.scale_vec(v, d)

@staticmethod
def from_bounding_box(box: BoundingBox, d: V2_t) -> Scalars:
v = box.rotate_rad(tx.rad(d)).br[:, 0, 0]
Expand Down Expand Up @@ -176,4 +182,4 @@ def get_envelope(self: Diagram, t: Optional[Affine] = None) -> Envelope:
assert segment.shape[:len(self.shape)] == self.shape, f"{segment.transform.shape} {self.shape}"
return Envelope(segment)

BatchEnvelope = Batched[Envelope, "*#B"]
BatchEnvelope = Batched[Envelope, "*#B"]
11 changes: 6 additions & 5 deletions chalk/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def animate(
) -> Tuple[List[Patch], tx.IntLike, tx.IntLike]:
return layout(self, height, width, draw_height)


def layout(
self: BatchDiagram,
height: tx.IntLike = 128,
Expand All @@ -45,19 +44,21 @@ def layout(

pad = tx.np.array(0.05)

envelope_width, envelope_height = envelope.size()

# infer width to preserve aspect ratio
if width is None:
width = tx.np.round(height * envelope.width / envelope.height).astype(
width = tx.np.round(height * envelope_width / envelope_height).astype(
int
)
else:
width = width
assert width is not None
# determine scale to fit the largest axis in the target frame size
α = tx.np.where(
envelope.width - width <= envelope.height - height,
height / ((1 + pad) * envelope.height),
width / ((1 + pad) * envelope.width),
envelope_width - width <= envelope_height - height,
height / ((1 + pad) * envelope_height),
width / ((1 + pad) * envelope_width),
)
s = self.scale(α).center_xy().pad(1 + pad)
e = s.get_envelope()
Expand Down
9 changes: 6 additions & 3 deletions chalk/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

def make_path(
segments: List[Tuple[tx.Floating, tx.Floating]], closed: bool = False
segments: Union[List[Tuple[tx.Floating, tx.Floating]], tx.P2_t], closed: bool = False
) -> Diagram:
p = from_list_of_tuples(segments, closed).stroke()
if isinstance(segments, (list, tuple)):
p = from_list_of_tuples(segments, closed).stroke()
else:
p = Path.from_array(segments, closed).stroke()
return p


Expand Down
Loading

0 comments on commit bf4b6ce

Please sign in to comment.