api.geometry design - mobileink/api.geometry GitHub Wiki

Design Goals

  • "Regular" 2D and 3D geometry. For lack of a better term. By that I mean that the capabilities required for photorealistic, CGI-style graphics are beyond the scope of this project. Why? Because a) I'm not very familiar with that stuff, and b) the basic use cases driving this project involve standard geometric tasks like specifying figures and compositions, finding tangents, intersecting regions, and so forth, rather than simulating real-world visual experience. Add text drawing as a special case. This is sufficient for just about everything we need to create user interfaces, charts, graphs, plots, diagrams, publication quality illustrations, etc. Examples: TikZ, D3, Asymptote, SVG, Processing, Processing.js.

To illustrate the point, consider the classic SVG Tiger. It's an impressive facsimile of a tiger head, but it's completely unrealistic. Nobody would ever mistake it for a real tiger, so it would not do for, say, Life of Pi. The core.geometry API should support the sort of capabilities illustrated by the SVG Tiger, but not the capabilities required to generate a life-like image. (Or more accurately: if you can do that with this, great, but it is not a design goal.)

  • Color, not light. A geometry is a model of space; to render a geometric object perceptible requires the addition of color. But light is a whole 'nother matter. In other words, if all you want to do is render a green circle you don't have to worry about how light works in the real world, or about properties of visual perception. For realistic CGI, by contrast, you would have to worry about how light of a certain quality is reflected off a green surface adjacent to a red surface, and lots of other things - you need a "Seurat model" of light and perception, rather than an abstract computational model of color.
  • Descriptive (declarative) syntax
  • Contrast: procedural syntax, e.g. Postscript, SVG. We say line a b rather than a moveto b lineto
  • Natural syntax
  • Syntax: for now we stick with Clojure's prefix-n-parens syntax. Infix syntax is more natural, and macros can make it work for Clojure (see Incanter's use of $= for this) but for now we follow the path of least resistance.
  • Terminology: "natural" means something like "standard mathematical terminology".
  • Text support: at least the level of support provided by Postscript, SVG, etc.; e.g. text along a curve.
  • Mathematical and technical text - ideally, same level of support as TeX
  • Seemless integration of text and geometry. Text is figure against ground, after all.
  • I18N:
  • full support for Unicode text, including RTL, Top to bottom, etc.
  • Orientation-independence. By that I mean that the "x" axis is not defined as increasing to the right. Axis directionality and angle must be explicitly specified. This means that figures will automatically be properly oriented in different coordinate spaces - e.g. switch first axis from the standard horizontal-increasing-rightward to vertical-increasing-downward, and your first-quadrant (upper right quadrant) figures appear in the third quadrant, mirrored and rotated.

Possible goals

  • Animation
  • Interactivity
  • Data-driven. The goal is to support "application" of geometric specifications to externally supplied data, just like XSL and D3. Or: parameterization of geometric specifications by external data.
  • Use of Z specification language to formally define type signatures and semantics
  • Express semantics in terms of dependent type theory. Just getting started with this so I'm not entirely sure what it would mean, but so far it looks to me like the vocab of dependent type theory is very expressive, in the sense that it makes it easy to say certain kinds of things that are difficult to express concisely and clearly without it. Note that we should be able to describe a language in terms of dependent type theory even if implementations do not involve programming languages with dependent types. The classic example being lists of length n as types parameterized by n. This suggests that we could think of a line of length n as a Line type parameterized by a length value, yielding "line of length n" as a type whose "inhabitants" are all lines of that length. Whether there is any real benefit to expressing things in this way I'm not yet sure.

Design Decision Points

  • One API or two? Drawing stuff always involves two things:
    • Computational geometry -- interpolating lines between points, finding tangents, computing the intersection of regions, etc. Computational geometry is device-independent, abstract.
    • Rendering -- mapping the results of computed geometries to display devices.

Most graphics toolkits combine these two functionalities - even the most primitive API must be capable of, e.g. computing the line between to points in order to implement a line function. But kits like JTS (Java Topology Suite) just do computational geometry. One reason you might want this is if you need to, say, compute some statistics (e.g. windspeed, accident rate, etc.) associated with a geographic region with no intention of actual drawing any pictures.

So the design question is whether to make two distinct API->protocol->implementation packages and how they would fit together.

  • Coordinates: to parenthesize or not to parenthesize. Many geometry APIs do not parenthesize, e.g.

    • line a b c d But parenthesis is more natural for pairs (point expressions): line (a,b) (c,d). The parens carry information. So we use parenthesized points.
  • Fixity: prefix, infix, or postfix are the three "natural" ways to do it:

    • line (a,b) (c,d)
    • (a,b) line (c,d)
    • (a,b) (c,d) line

To support infix or postfix we would have to use a macro, e.g. ($= (a,b) line (c,d)). So we stick with prefix notation.

  • To macroize or not to macroize. For example:
    1. (line '(0,0) '(1,1))
    2. (line (0,0) (1,1))

Here i is close to natural, but it has those pesky ' marks; ii is more natural. We can support this if we make "line" a macro.