Skip to content

Commit 029d06a

Browse files
committed
Extend 2D PointBox to handle (roughly) PointSize.
Numerous other small adjustments were made too.
1 parent 38b6d63 commit 029d06a

4 files changed

Lines changed: 47 additions & 18 deletions

File tree

mathics/builtin/graphics.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,7 +1279,6 @@ class Point(Builtin):
12791279
<dd>represents a number of point primitives.
12801280
</dl>
12811281
1282-
>> Graphics[Point[{0,0}]]
12831282
= -Graphics-
12841283
12851284
>> Graphics[Point[Table[{Sin[t], Cos[t]}, {t, 0, 2. Pi, Pi / 15.}]]]
@@ -1292,10 +1291,29 @@ class Point(Builtin):
12921291
pass
12931292

12941293

1294+
# FIXME: We model points as line segments which
1295+
# is kind of wrong.
12951296
class PointBox(_Polyline):
1297+
"""
1298+
A Bounding box for a list of points.
1299+
object attributes:
1300+
edge_color: _Color
1301+
point_radius: radius of each point
1302+
"""
12961303
def init(self, graphics, style, item=None):
12971304
super(PointBox, self).init(graphics, item, style)
12981305
self.edge_color, self.face_color = style.get_style(_Color, face_element=True)
1306+
1307+
# Handle PointSize in a hacky way for now.
1308+
point_size, _ = style.get_style(PointSize, face_element=False)
1309+
if point_size is None:
1310+
point_size = PointSize(self.graphics, value=0.005)
1311+
1312+
# FIXME: we don't have graphics options. Until we do, we'll
1313+
# just assume an image width of 400
1314+
image_width = 400
1315+
self.point_radius = (image_width * point_size.value)
1316+
12991317
if item is not None:
13001318
if len(item.leaves) != 1:
13011319
raise BoxConstructError
@@ -1307,6 +1325,19 @@ def init(self, graphics, style, item=None):
13071325
else:
13081326
raise BoxConstructError
13091327

1328+
def extent(self):
1329+
"""Returns a list of bounding-box coordinates each point in the PointBox"""
1330+
l = self.point_radius
1331+
result = []
1332+
for line in self.lines:
1333+
for c in line:
1334+
x, y = c.pos()
1335+
result.extend(
1336+
[(x - l, y - l), (x - l, y + l), (x + l, y - l), (x + l, y + l)]
1337+
)
1338+
return result
1339+
1340+
13101341

13111342
class Line(Builtin):
13121343
"""
@@ -2382,6 +2413,7 @@ def __init__(self, content, evaluation, neg_y=False):
23822413
self.xmin = self.ymin = self.pixel_width = None
23832414
self.pixel_height = self.extent_width = self.extent_height = None
23842415
self.view_width = None
2416+
self.content = content
23852417

23862418
def translate(self, coords):
23872419
if self.pixel_width is not None:
@@ -2512,8 +2544,8 @@ def _get_image_size(self, options, graphics_options, max_width):
25122544
def _prepare_elements(self, leaves, options, neg_y=False, max_width=None):
25132545
if not leaves:
25142546
raise BoxConstructError
2515-
graphics_options = self.get_option_values(leaves[1:], **options)
2516-
background = graphics_options["System`Background"]
2547+
self.graphics_options = self.get_option_values(leaves[1:], **options)
2548+
background = self.graphics_options["System`Background"]
25172549
if (
25182550
isinstance(background, Symbol)
25192551
and background.get_name() == "System`Automatic"
@@ -2523,10 +2555,10 @@ def _prepare_elements(self, leaves, options, neg_y=False, max_width=None):
25232555
self.background_color = _Color.create(background)
25242556

25252557
base_width, base_height, size_multiplier, size_aspect = self._get_image_size(
2526-
options, graphics_options, max_width
2558+
options, self.graphics_options, max_width
25272559
)
25282560

2529-
plot_range = graphics_options["System`PlotRange"].to_python()
2561+
plot_range = self.graphics_options["System`PlotRange"].to_python()
25302562
if plot_range == "System`Automatic":
25312563
plot_range = ["System`Automatic", "System`Automatic"]
25322564

@@ -2658,7 +2690,7 @@ def get_range(min, max):
26582690
ymax += h * 0.02
26592691

26602692
axes.extend(
2661-
self.create_axes(elements, graphics_options, xmin, xmax, ymin, ymax)
2693+
self.create_axes(elements, self.graphics_options, xmin, xmax, ymin, ymax)
26622694
)
26632695

26642696
return elements, calc_dimensions
@@ -2725,6 +2757,7 @@ def boxes_to_mathml(self, leaves=None, **options) -> str:
27252757
elements, calc_dimensions = self._prepare_elements(leaves, options, neg_y=True)
27262758
xmin, xmax, ymin, ymax, w, h, width, height = calc_dimensions()
27272759
data = (elements, xmin, xmax, ymin, ymax, w, h, width, height)
2760+
elements.view_width = w
27282761

27292762
# FIXME: SVG is the only thing we can convert MathML into.
27302763
# Handle other graphics formats.

mathics/doc/tex/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ doc_tex_data.pcl:
1616
mathics.pdf: mathics.tex documentation.tex logo-text-nodrop.pdf logo-heptatom.pdf doc_tex_data.pcl
1717
$(LATEXMK) -f -pdf -pdflatex="$(XETEX) -halt-on-error" mathics
1818

19+
#: Build test PDF
20+
mathics-test.pdf: mathics-test.tex
21+
$(LATEXMK) -f -pdf -pdflatex="$(XETEX) -halt-on-error" mathics-test
22+
23+
1924
#: Generate logos used in the titlepage
2025
logo-heptatom.pdf logo-text-nodrop.pdf:
2126
(cd .. && $(BASH) ./images.sh)
@@ -34,3 +39,4 @@ clean:
3439
rm -f mathics_*.* || true
3540
rm -f mathics-*.* documentation.tex || true
3641
rm -f mathics.pdf mathics.dvi data_tex_data.pcl || true
42+
rm -f mathics-test.pdf mathics-test.dvi || true

mathics/formatter/svg.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ def components():
133133
add_conversion_fn(FilledCurveBox, filled_curve_box)
134134

135135
def graphics_box(self, leaves=None, **options) -> str:
136+
136137
if not leaves:
137138
leaves = self._leaves
138139

@@ -164,17 +165,6 @@ def graphics_box(self, leaves=None, **options) -> str:
164165
svg_body,
165166
)
166167

167-
168-
# FIXME:
169-
# Length calculation with PointBox is off by PointSize
170-
# point_size, _ = self.style.get_style(PointSize, face_element=False)
171-
# For others, I guess we just have this extra margin around the edge.
172-
point_size = 14.06 # Really 14.05333..5
173-
xmin -= point_size
174-
ymin -= point_size
175-
w += 2 * point_size
176-
h += 2 * point_size
177-
178168
if options.get("noheader", False):
179169
return svg_body
180170
svg_main = """

test/test_formatter/test_svg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def test_svg_point():
7676
# Circles are implemented as ellipses with equal major and minor axes.
7777
# Check for that.
7878
print(inner_svg)
79-
matches = re.match(r'^<circle cx="(\S+)" cy="(\S+)" r="(\S+)" .*/>', inner_svg)
79+
matches = re.match(r'^<circle cx="(\S+)" cy="(\S+)"', inner_svg)
8080
assert matches
8181
assert matches.group(1) == matches.group(2)
8282

0 commit comments

Comments
 (0)