Skip to content

tgetgood/lemonade

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lemonade

Experiment in higher order visual programming.

Check out Expanse to see it in use.

Overview

This is a library for doing vector graphics in a data driven idiomatic clojure fashion. Feel free to think of it as an extension of lisp from the lambda calculus to vector geometry. That’s how I think of it in any case.

The name is a reference to a name I thought up for a presentation once. It’s not a great name, but it could be worse.

Breakdown

lemonade.core: The core graphics primitives.

lemonade.math: Mathematical and interop helpers.

lemonade.geometry: Geometric model of the rendered world to map back and forth from screen coordinates to fibres of the render tree.

Renderers are in lemonade.renderers.*. There are currently only 2, an HTML Canvas 2d rendering context renderer for the browser and a quil renderer for JVM Clojure. Both renderers are working and should produce identical results. I’d be much obliged to anyone who can point out where they don’t.

The definition of shapes is probably going to change from one based on curves and winding numbers as most graphics libraries do to a constructive topology. That is glue together locally convex simply connected shapes to produce non simple shapes, and subtract one shape from another. I’m still thinking out the details.

Getting Started

Expanse is the place to go if you want to see Lemonade in action or play with running code.

Testing

Having a fully declarative model of the UI allows headless testing of most UI components. You can determine the exact pixel coordinates of any shape or the colour of any pixel without rendering anything. At least in principle. Lemonade itself needs some heavy testing to make sure this is true.

Working on

Regions

User defined regions can be tricky.

The systems I know (processing, canvas, opengl) require you to draw a region explicitly. That is you declare you’re starting a region, draw a bunch of curves and then eclare you’ve finished the region. This gets compiled into special code that uses winding number calculations to separate the inside from the outside.

I don’t want that. I want you to be able to define a path, and then concatenate that path with transformations of itself or other paths, and then tell the compiler when you expect the path to have closed. This is dynamic in the sense that you might be wrong and it will trigger a runtime error.

It’s basically impossible to compose shapes if they have to be defined at compile time.

Something like

	 (l/with-style {:fill :blue}
		 [s
			(l/rotate s 90)
			(l/reflect s corner [1 1])
			bottom-curve])

Should be all you need to specify to get a blue shape with the complex boundary specified. If they boundary isn’t closed, we have an error and I have to think about what to do there. As is, the fill just doesn’t happen, which I think is good enough for now.

Shape algebra

Unions, intesections, and differences of shapes should produce first class shapes. As is, I can only render them directly, if they end up deep in a nested data structure, I can’t do much with them.

The Name

Lemonade is a bad pun on the W3C giving you a lemon. Canvas actually isn’t that bad compared to everything else out there, but that’s beside the point. It’s a flat name.

Candidates

Falloleen - Don’t ask, just a pretty and unique name.

References

Functional Geometry Pictures: A Simple Strutured Graphics Model

License

Copyright © 2018 Thomas Getgood

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

About

High level graphics language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published