Skip to content

Commit

Permalink
Start adding Alignment to InsetBox in 2D graphs (#1234)
Browse files Browse the repository at this point in the history
Add the notion of text alignment of InsetBox which is typically used in drawing axes. The text for an x (horizontal) axis is under the ticks while the text for a y (vertical) axis is to the left.

Here we've done this for asymptote and SVG. More that could be done, but this is a small start.
  • Loading branch information
rocky authored Dec 21, 2024
1 parent b052251 commit 6b19e87
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
13 changes: 13 additions & 0 deletions mathics/builtin/box/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,16 @@ def add_element(element):
),
]
):
# Where should the placement of tick mark labels go?
if index == 0:
# x labels go under tick marks
alignment = "bottom"
elif index == 1:
# y labels go to the left of tick marks
alignment = "left"
else:
alignment = None

if axes[index]:
add_element(
LineBox(
Expand Down Expand Up @@ -858,6 +868,7 @@ def add_element(element):
),
opos=p_self0(1),
opacity=1.0,
alignment=alignment,
)
)
for x in ticks_small:
Expand Down Expand Up @@ -992,6 +1003,7 @@ def init(
pos=None,
opos=(0, 0),
opacity=None,
alignment=None,
):
super(InsetBox, self).init(graphics, item, style)

Expand All @@ -1008,6 +1020,7 @@ def init(
opacity = Opacity(1.0)

self.opacity = opacity
self.alignment = alignment

if item is not None:
if len(item.elements) not in (1, 2, 3):
Expand Down
20 changes: 12 additions & 8 deletions mathics/format/asy.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,21 +409,25 @@ def graphics_elements(self, **options) -> str:
def inset_box(self, **options) -> str:
"""Asymptote formatting for boxing an Inset in a graphic."""
x, y = self.pos.pos()

alignment = "SW"
if hasattr(self, "alignment"):
if self.alignment == "bottom":
# This is typically done for labels under the x axis.
alignment = "S"
elif self.alignment == "left":
# This is typically done for labels to the left of the y axis.
alignment = "W"

opacity_value = self.opacity.opacity if self.opacity else None
content = self.content.boxes_to_tex(evaluation=self.graphics.evaluation)
# FIXME: don't hard code text_style_opts, but allow these to be adjustable.
font_size = 3
pen = asy_create_pens(
edge_color=self.color, edge_opacity=opacity_value, fontsize=font_size
)
asy = """// InsetBox
label("$%s$", (%s,%s), %s, %s);\n""" % (
content,
x,
y,
"align=SW",
pen,
)
asy = f"""// InsetBox
label("${content}$", ({x},{y}), align={alignment}, {pen});\n"""
return asy


Expand Down
12 changes: 11 additions & 1 deletion mathics/format/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,18 @@ def inset_box(self, **options) -> str:
opacity=self.opacity.opacity,
)
text_pos_opts = f'x="{x}" y="{y}" ox="{self.opos[0]}" oy="{self.opos[1]}"'

alignment = " dominant-baseline:hanging;"
if hasattr(self, "alignment"):
if self.alignment == "bottom":
# This is typically done for labels under the x axis.
alignment = " dominant-baseline:hanging; text-anchor:middle;"
elif self.alignment == "left":
# This is typically done for labels to the left of the y axis.
alignment = " dominant-baseline:middle; text-anchor:end;"

# FIXME: don't hard code text_style_opts, but allow these to be adjustable.
text_style_opts = "text-anchor:end; dominant-baseline:hanging;"
text_style_opts = alignment
content = self.content.boxes_to_text(evaluation=self.graphics.evaluation)
font_size = f'''font-size="{options.get("point_size", "10px")}"'''
svg = f'<text {text_pos_opts} {font_size} style="{text_style_opts} {css_style}">{content}</text>'
Expand Down

0 comments on commit 6b19e87

Please sign in to comment.