• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqt誰得windowscocoapythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

A categorical programming language


Commit MetaInfo

修订版714d4c0fb39fab3e2129852f378db0b459800ac9 (tree)
时间2022-06-20 14:10:40
作者Corbin <cds@corb...>
CommiterCorbin

Log Message

Let the viewport for drawings automatically scale.

更改概述

差异

--- a/accept-jelly.py
+++ b/accept-jelly.py
@@ -44,7 +44,7 @@ with open("jelly/src/main.rs", "r") as handle:
4444 if match is not None:
4545 rules.append((match[1], match[2], match[3]))
4646
47-print("Asking jelly whether", len(rules), "rules are sufficiently clear")
47+print("Asking jelly whether its own", len(rules), "rules are sufficiently clear")
4848 explosiveRules = 0
4949 for name, source, target in rules:
5050 jellied = jellify(source)
--- a/cammy-rpy/animate.py
+++ b/cammy-rpy/animate.py
@@ -7,7 +7,7 @@ from rpython.rtyper.lltypesystem import rffi
77
88 from cammylib import caca
99 from cammylib.cam import compileArrow
10-from cammylib.colors import hdr2byte
10+from cammylib.colors import hdr2byte, rescale
1111 from cammylib.elements import F, P, TypeFail
1212 from cammylib.parser import parse
1313
@@ -20,20 +20,6 @@ def resize(displayWidth, displayHeight):
2020 print "Buffer is %d x %d" % (bufferWidth, bufferHeight)
2121 return displayWidth, displayHeight, bufferWidth, bufferHeight
2222
23-def rescale(width, height):
24- woffset = width >> 1
25- hoffset = height >> 1
26- # Keep pixels square-ish, and let window flexibly scale.
27- scale = min(width, height) >> 1
28- lx = -woffset / scale
29- ly = -hoffset / scale
30- rx = (width - woffset) / scale
31- uy = (height - hoffset) / scale
32- # View
33- print "Viewport is at (%f,%f) (lower left) to (%f,%f) (upper right)" % (
34- lx, ly, rx, uy)
35- return woffset, hoffset, scale
36-
3723 def drawDisplay(cam, canvas, display):
3824 displayWidth, displayHeight, w, h = resize(
3925 caca.get_canvas_width(canvas),
--- a/cammy-rpy/cammylib/colors.py
+++ b/cammy-rpy/cammylib/colors.py
@@ -11,3 +11,15 @@ def linear2sRGB(u):
1111
1212 def hdr2byte(c):
1313 return chr(int(255 * max(0.0, min(1.0, linear2sRGB(c)))))
14+
15+def rescale(width, height):
16+ woffset = width >> 1
17+ hoffset = height >> 1
18+ # Keep pixels square-ish, and let window flexibly scale.
19+ scale = min(width, height) >> 1
20+ # lx = -woffset / scale
21+ # ly = -hoffset / scale
22+ # rx = (width - woffset) / scale
23+ # uy = (height - hoffset) / scale
24+ # print "Viewport is at (%f,%f) (lower left) to (%f,%f) (upper right)" % (lx, ly, rx, uy)
25+ return woffset, hoffset, scale
--- a/cammy-rpy/draw.py
+++ b/cammy-rpy/draw.py
@@ -6,49 +6,16 @@ import math
66
77 from rpython.rlib.jit import JitDriver, unroll_safe #, set_param
88 from rpython.rlib.rfile import create_stdio
9-from rpython.rlib.rfloat import string_to_float
10-from rpython.rlib.rstring import StringBuilder, split
9+from rpython.rlib.rstring import StringBuilder
1110 # from rpython.rlib import rvmprof
1211
1312 from cammylib.cam import compileArrow
14-from cammylib.colors import hdr2byte
13+from cammylib.colors import hdr2byte, rescale
1514 from cammylib.elements import F, P, TypeFail
1615 from cammylib.parser import parse
1716 from cammylib import stb
1817
1918
20-# Borrowed from stub.scm and Typhon's colors.mt
21-
22-def scale(bot, top, x):
23- d = top - bot
24- return bot + d * x
25-
26-# Pixel area: 4 / (w * h)
27-# Pixel radius: √(area / pi) = 2 / √(w * h * pi) = (2 / √pi) / √(w * h)
28-# This constant is the first half of that.
29-TWOSQRTPI = 2.0 / math.sqrt(math.pi)
30-
31-class Window(object):
32- _immutable_ = True
33-
34- def __init__(self, corners, width, height):
35- self._corners = corners[0], corners[1], corners[2], corners[3]
36- self._w = width
37- self._h = height
38- area = abs((corners[0] - corners[2]) * (corners[1] - corners[3]))
39- self.pixelRadius = TWOSQRTPI * area / math.sqrt(width * height)
40-
41- def coordsForPixel(self, i):
42- w = i % self._w
43- h = i // self._w
44- iw = 1.0 / self._w
45- dw = 0.5 * iw
46- ih = 1.0 / self._h
47- dh = 0.5 * ih
48- c1 = scale(self._corners[0], self._corners[2], dw + iw * w)
49- c2 = scale(self._corners[1], self._corners[3], dh + ih * h)
50- return c1, c2
51-
5219 # Transcribed from Monte:
5320 # https://github.com/monte-language/typhon/blob/master/mast/lib/welford.mt
5421 class Welford(object):
@@ -102,42 +69,51 @@ def multisample(program, radius, x, y):
10269 g += rgb.second().first().f()
10370 b += rgb.second().second().f()
10471 l = len(offsets)
105- return hdr2byte(r / l), hdr2byte(g / l), hdr2byte(b / l), cost // len(offsets)
72+ return hdr2byte(r / l), hdr2byte(g / l), hdr2byte(b / l), cost // l
10673
107-def drawPixels(size, program, window):
74+# Pixel area: 4 / (w * h)
75+# Pixel radius: √(area / pi) = 2 / √(w * h * pi) = (2 / √pi) / √(w * h)
76+# This constant is the first half of that.
77+TWOSQRTPI = 2.0 / math.sqrt(math.pi)
78+
79+def drawPixels(program, w, h):
10880 _, stdout, _ = create_stdio()
109- sb = StringBuilder(size * 3)
11081 cost = Welford()
82+
11183 i = 0
112- while i < size:
113- c1, c2 = window.coordsForPixel(i)
114- r, g, b, c = multisample(program, window.pixelRadius, c1, c2)
115- sb.append(r + g + b)
116- cost.observe(c)
117- i += 1
118- if not (i % 1000):
119- stdout.write(".")
120- stdout.flush()
84+ woff, hoff, scale = rescale(w, h)
85+ pixelRadius = TWOSQRTPI / math.sqrt(w * h)
86+ stdout.write("scale is %f, pixel radius is %f\n" % (scale, pixelRadius))
87+ buf = StringBuilder(w * h * 3)
88+ # Flip y-axis to get traditional quadrants.
89+ for y in range(h - hoff, -hoff, -1):
90+ for x in range(-woff, w - woff):
91+ c1 = x / scale
92+ c2 = y / scale
93+ r, g, b, c = multisample(program, pixelRadius, c1, c2)
94+ buf.append(r + g + b)
95+ cost.observe(c)
96+ i += 1
97+ if not (i % 1000):
98+ stdout.write(".")
99+ stdout.flush()
121100 stdout.write("\n")
122101 stdout.write("Cost: %f / %f / %f / %f (avg/stddev/skew/kurt)" % cost.moments())
123102 stdout.write("\n")
124- return sb.build()
103+ return buf.build()
125104
126-def drawPNG(program, filename, corners, width, height):
127- window = Window(corners, width, height)
128- size = width * height
129- buf = drawPixels(size, program, window)
105+def drawPNG(program, filename, width, height):
106+ buf = drawPixels(program, width, height)
130107 channels = 3
131108 stb.i_write_png(filename, width, height, channels, buf, width * channels)
132109
133110
134-def doDraw(prog, window, width, height, out):
111+def doDraw(prog, width, height, out):
135112 # set_param(None, "trace_limit", 50001)
136113
137114 # profiler = open("vmprof.dat", "wb")
138115 # rvmprof.enable(profiler.fileno(), 0.001)
139116
140- window = [string_to_float(s) for s in split(window)]
141117 width = int(width)
142118 height = int(height)
143119 with open(prog) as handle:
@@ -145,7 +121,7 @@ def doDraw(prog, window, width, height, out):
145121 arrow = sexp.buildArrow()
146122 cam = compileArrow(arrow)
147123 try:
148- drawPNG(cam, out, window, width, height)
124+ drawPNG(cam, out, width, height)
149125 except TypeFail as tf:
150126 print "Type failure:", tf.reason
151127 raise
--- a/cammy-rpy/main.py
+++ b/cammy-rpy/main.py
@@ -19,7 +19,7 @@ def help(exe, problem):
1919 print "Usage:"
2020 print " animate PROG WIDTH HEIGHT Animate in the terminal"
2121 print " comb Generate a dependency graph for the hive"
22- print " draw PROG WINDOW WIDTH HEIGHT OUT Draw a picture"
22+ print " draw PROG WIDTH HEIGHT OUT Draw a picture"
2323 print " frame CATS Compile to categories and remove sugar"
2424 print " freeze Sugar an expression with respect to the hive"
2525 print " rename SOURCE TARGET Rename an expression in the hive"
@@ -44,9 +44,9 @@ def main(argv):
4444 elif command == "comb":
4545 return doComb(hivepath)
4646 elif command == "draw":
47- if len(argv) != 7:
48- help(exe, "draw takes five arguments")
49- return doDraw(argv[2], argv[3], argv[4], argv[5], argv[6])
47+ if len(argv) != 6:
48+ help(exe, "draw takes four arguments")
49+ return doDraw(argv[2], argv[3], argv[4], argv[5])
5050 elif command == "frame":
5151 if len(argv) != 3:
5252 help(exe, "frame takes one argument")
--- /dev/null
+++ b/hive/burning-ship-detail.cammy
@@ -0,0 +1,8 @@
1+(setup-viewport
2+ (pair
3+ (ratio nat/7 nat/4)
4+ (comp (ratio nat/3 nat/100) f-negate))
5+ (comp nat/20 (comp nat/to-f f-recip)))
6+
7+A nice closeup of a self-similar instance of the Burning Ship fractal along
8+the main line.
--- a/hive/demo/burning-ship-color.cammy
+++ b/hive/demo/burning-ship-color.cammy
@@ -1,7 +1,9 @@
11 (comp
22 (comp
3- (fractal-membership-color v2/burning-ship (comp nat/64 succ))
4- (monads/maybe/guard (pair/of nat/lt-eq? id (fun/const nat/64))))
3+ burning-ship-detail
4+ (comp
5+ (fractal-membership-color v2/burning-ship (comp nat/64 succ))
6+ (monads/maybe/guard (pair/of nat/lt-eq? id (fun/const nat/64)))))
57 (case (comp (comp nat/to-f f/radians-to-turns) h2rgb) v3/rgb/black))
68
79 Draw membership for the [Burning Ship
--- /dev/null
+++ b/hive/nat/100.cammy
@@ -0,0 +1 @@
1+(comp nat/10 nat/sqr)
\ No newline at end of file
--- /dev/null
+++ b/hive/nat/20.cammy
@@ -0,0 +1 @@
1+(comp nat/10 nat/double-alt)
\ No newline at end of file
--- /dev/null
+++ b/hive/ratio.cammy
@@ -0,0 +1 @@
1+(comp (comp (pair @0 @1) (v2/map nat/to-f)) f/div)
\ No newline at end of file
--- /dev/null
+++ b/hive/scale-v2-by-const.cammy
@@ -0,0 +1 @@
1+(comp (pair id (fun/const @0)) v2/scale-by)
\ No newline at end of file
--- /dev/null
+++ b/hive/setup-viewport.cammy
@@ -0,0 +1,5 @@
1+(comp (scale-v2-by-const @1) (sub-v2-by-const @0))
2+
3+Set up a preferred viewport for 2D rendering. The viewport is centered at the
4+given location, and drawn with at least the given radius circumscribed within
5+the rendering box.
--- /dev/null
+++ b/hive/sub-v2-by-const.cammy
@@ -0,0 +1 @@
1+(comp (pair id (fun/const @0)) (v2/map2 f/sub))
\ No newline at end of file