Lua bindings for geometric objects

All Ipelib objects have constructors of the form:

     v = ipe.Vector()
     m = ipe.Matrix()
     m = ipe.Translation()  -- another Matrix constructor
     m = ipe.Rotation()     -- yet another Matrix constructor
     r = ipe.Rect()
     l = ipe.Line()
     l = ipe.LineThrough()  -- another Line constructor
     l = ipe.Bisector()     -- yet another Line constructor
     s = ipe.Segment()
     b = ipe.Bezier()
     a = ipe.Arc()

Note that ipe::Angle and ipe::Linear are not bound in Lua. Use numbers and ipe.Matrix instead. A useful method for angles is:

    beta = ipe.normalizeAngle(alpha, lowLimit)

# Vector

ipe.Vector binds ipe::Vector. There are the following methods:

    v = ipe.Vector()         -- zero vector
    v = ipe.Vector(x, y)
    v = ipe.Direction(alpha) -- unit vector in this direction
    a = v.x                  -- read only access to x and y coordinates
    b = v.y

    v:len() -- returns norm of vector
    v:sqLen() -- returns square of norm
    v:normalized() -- returns this vector normalized
    v:orthogonal() -- returns this vector rotated left by 90 degrees
    v:factorize(u) -- factors v = lambda u + x, where x orth. to u, u is unit
    v:angle()     -- return direction
    v == w        -- vector equality
    v ~= w
    -v            -- unary minus
    v + w         -- vector addition
    v - w         -- vector difference
    5 * v         -- multiplication with a scalar
    v * 5         -- multiplication with a scalar
    v .. w        -- dot product

# Matrix

ipe.Matrix binds ipe::Matrix. It has the following methods:

    m = ipe.Matrix()                        -- identity matrix
    m = ipe.Matrix(a1, a2, a3, a4)          -- linear transformation
    m = ipe.Matrix(a1, a2, a3, a4, a5, a6)  -- affine transformation
    m = ipe.Matrix( { a1, a2, a3, a4, a5, a6 } ) -- same from table
    m = ipe.Rotation(alpha)                 -- rotation matrix
    m = ipe.Translation(v)                  -- v is a vector
    m = ipe.Translation(x, y)

    m1 == m2          -- matrix equality
    m1 * m2           -- matrix multiplication
    m * v             -- matrix * vector
    m * arc           -- matrix * arc

    m:elements()      -- returns six-element array with elements

    m:isIdentity()
    m:isSingular()
    m:inverse()
    m:translation()   -- return translation component
    m:linear()        -- returns matrix without the translation component

# Rect

ipe.Rect binds ipe::Rect. This is the only mutable geometric object - take care not to be surprised when ipe.Rect objects are shared.

It has the following methods:

    r = ipe.Rect()    -- empty
    r:isEmpty()
    r:topRight()
    r:bottomLeft()
    r:topLeft()
    r:bottomRight()
    r:left()
    r:right()
    r:bottom()
    r:top()
    r:width()
    r:height()
    r:add(v)          -- extend to cover vector v
    r1:add(r2)        -- extend to cover rectangle r2
    r1:clipTo(r2)     -- clip r1 to lie inside r2
    r:contains(v)
    r1:contains(r2)
    r1:intersects(r2)

# Line

ipe.Line binds ipe::Line. It has the following methods:

    l = ipe.Line(p, dir)      -- dir must be unit vector
    l = ipe.LineThrough(p, q)
    l = ipe.Bisector(p, q)

    -- l:side() returns +1 if v lies to the left side of the line,
    -- 0 if on line, -1 if on the right side
    l:side(v)
    l:point()                 -- starting point of line
    l:dir()                   -- unit direction vector
    l:normal()                -- unit normal vector pointing to the left side
    l:distance(v)             -- returns distance from point to line
    l1:intersects(l2)         -- returns intersection point or nil
    l:project(p)              -- projection of point on line

# Segment

ipe.Segment binds ipe::Segment. It has the following methods:

    s = ipe.Segment(p, q)
    p, q = s:endpoints()      -- returns both endpoints
    s:line()                  -- returns an ipe.Line
    s:project(p)              -- returns projection or nil
    s:distance(p)
    s:intersects(l)           -- return intersection point or nil
    s1:intersects(s2)

# Bezier

ipe.Bezier binds ipe::Bezier. It has the following methods:

    b = ipe.Bezier(v1, v2, v3, v4)
    b:point(t)                -- point at value t
    v1, v2, v3, v4 = b:controlpoints()  -- returns all four control points
    b:bbox()
    t, p = b:snap(pos)

    -- intersections:
    -- x is line, segment, or bezier
    -- returns table of intersection points
    b:intersect(x)

# Arc

ipe.Arc binds ipe::Arc. It has the following methods:

    a = ipe.Arc(m)            -- ellipse defined by ipe.Matrix m
    a = ipe.Arc(m, p, q)      -- arc from p to q
    a = ipe.Arc(m, alpha, beta)

    a:endpoints()             -- returns two endpoints
    a:angles()                -- returns two angles
    a:bbox()
    a:matrix()
    a:isEllipse()
    alpha, p = a:snap(pos)

    -- intersections:
    -- x is line, segment, arc, or bezier
    -- returns table of intersection points
    a:intersect(x)