Geomerative

Introduction

Geomerative is a library for Processing. It extends 2D geometry operations to facilitate generative geometry. Includes a TrueType font and an SVG interpreters. This library exposes the shapes (such as vector drawings or typographies) in a more approchable way. Geomerative makes it easy to access the paths, the handles and the points, making it easy to develop generative typography and geometry pieces in Processing.

Download

Geomerative (rev 29) (December 27 2009)

unzip the contents of this file to /path/to/sketchbook/libraries

Credits

Creator:
Ricard Marxer Follow ricardmp on Twitter
Collaborator:
Mark Luffel
Overview, examples and bug fixes:
Florian Jenett

Works

Geomerative has been used in the following projects:

Overview

The library is composed of 4 basic elements (RShape, RPolygon, RMesh and RGroup) all of which support a set of common methods such as: accessing (getCurvePoints, getPoints,...), transforming (translate, rotate, scale,...), styling (setStroke, setStrokeColor, setStrokeWeight, setFill, setFillColor,...) and drawing (draw). Additionally the library has 2 interpreters that will allow the user to import shapes from TTF fonts and SVG vector drawings into the library's classes.

Elements

RShape

/*
*    geomerative example
*    http://www.ricardmarxer.com/geomerative
 *
 *    fjenett 20080417
 */

import geomerative.*;

RShape shp;

void setup()
{
    size(400,400);
    smooth();
    
    RGeomerative.init(this);
    
    shp = new RShape();
    
    shp.addMoveTo( 0 , 141 );        // zeichenbefehle, vergleiche beginShape, vertex, bezierVertex
    shp.addLineTo( 2 , 133 );
    shp.addLineTo( 34 , 133 );
    shp.addLineTo( 60 , 9 );
    shp.addLineTo( 38 , 9 );
    shp.addBezierTo( 20 , 9 , 16 , 12 , 12 , 30 );
    shp.addLineTo( 9 , 46 );
    shp.addLineTo( 0 , 46 );
    shp.addLineTo( 10 , 0 );
    shp.addLineTo( 123 , 0 );
    shp.addLineTo( 113 , 46 );
    shp.addLineTo( 104 , 46 );
    shp.addLineTo( 107 , 30 );
    shp.addBezierTo( 111 , 12 , 109 , 9 , 91 , 9 );
    shp.addLineTo( 69 , 9 );
    shp.addLineTo( 43 , 133 );
    shp.addLineTo( 75 , 133 );
    shp.addLineTo( 73 , 141 );
    shp.addLineTo( 0 , 141 );
    shp.addClose();
}

void draw()
{
    background(255);
    translate(140,120);
    
    stroke( 120 );
    strokeWeight( 3 );
    fill( 220 );

    shp.draw();
}

RPolygon

/*
*    geomerative example
*    http://www.ricardmarxer.com/geomerative
*
*    fjenett 20080417
*/

import geomerative.*;

RPolygon ply;

void setup()
{
    size(400,400);
    
    RGeomerative.init(this);
    
    ply = new RPolygon();
    
    for ( int i=0; i<360; i++ )
    {
        float rad = radians(i);
        float rad2 = radians(i*12);
        ply.addPoint( sin(rad)*120+sin(rad2)*20, cos(rad)*120+cos(rad2)*20 );
    }
}

void draw()
{
    background(255);
    translate(width/2,height/2);
    
    stroke( 120 );
    strokeWeight( 3 );
    fill( 220 );

    ply.draw();
}

RMesh

/*
*    geomerative example
*    http://www.ricardmarxer.com/geomerative
*
*    fjenett 20080419
*/

import geomerative.*;

RMesh msh;

void setup()
{
    size(400,400);
    frameRate( 2 );
    
    RGeomerative.init(this);
    
    strokeWeight( 1.2 );
}

void draw()
{
    background(130);
    
    RPolygon pl = RPolygon.createRing( random(80,160), random(10,50), int(random(5,15)) ).toPolygon();
    msh = pl.toMesh();
    
    translate( width/2, height/2 );
    msh.draw( );
}

RGroup

/*
*    geomerative example
*    http://www.ricardmarxer.com/geomerative
*
*    glyphen eines fonts auslesen
*
*    fjenett 20080417
*/

import geomerative.*;

RFont font;

void setup()
{
    size(400,400);
    smooth();
    
    RGeomerative.init(this);

    font = new RFont( "lucon.ttf", 100, RFont.CENTER);
}

void draw()
{
    background(255);
    translate(width/2,height/2);
    
    RGroup grp = font.toGroup("Hello?");                                // text in ein gruppen-objekt umwandeln
    
    for ( int i = 0; i < grp.elements.length; i++ )                     // elemente durchlaufen
    {
        RShape shp = grp.elements[i].toShape();                         // gruppen-element in shape-objekt umwandeln
        
        for ( int ii = 0; ii < shp.paths.length; ii++ )             // shapes durchlaufen
        {
            RPath sushp = shp.paths[ii];                        // path-objekt
            
            for ( int iii = 0; iii < sushp.commands.length; iii++ )     // zeichen-kommando-objekte durchlaufen
            {
                RPoint[] pnts = sushp.commands[iii].getPoints();        // punkte des kommando-objekts
                
                switch( sushp.commands[iii].getCommandType() )          // je nach kommando-art anderern befehl ausfŸhren
                {
                    case RCommand.LINETO:
                        line( pnts[0].x, pnts[0].y, pnts[1].x, pnts[1].y );
                        break;
                    case RCommand.QUADBEZIERTO:    // eigentlich falsch, denn bezier() ist kubisch
                        bezier( pnts[0].x, pnts[0].y, pnts[1].x, pnts[1].y, pnts[1].x, pnts[1].y, pnts[2].x, pnts[2].y );
                       break;
                    case RCommand.CUBICBEZIERTO:
                        bezier( pnts[0].x, pnts[0].y, pnts[1].x, pnts[1].y, pnts[2].x, pnts[2].y, pnts[3].x, pnts[3].y );
                       break;
                }
            }
        }
    }
}

Interpreters

RFont

/*
*    geomerative example
*    http://www.ricardmarxer.com/geomerative
*
*    fjenett 20080417
*/

import geomerative.*;

RFont font;

void setup()
{
    size(400,400);
    
    RGeomerative.init(this);

    font = new RFont( "lucon.ttf", 72, RFont.LEFT);
}

void draw()
{
    background(0,100,50);
    translate(width/2-200,height/2-100);
    
    font.draw("Hello?");
}

RSVG

/*
*    geomerative example
*    http://www.ricardmarxer.com/geomerative
*
*    fjenett 20080417
*/

import geomerative.*;

RSVG svg;

void setup()
{
    size(800,800);
    frameRate( 30 );
    
    RGeomerative.init(this);
    
    svg = new RSVG( );
}

void draw()
{
    background(255);
    svg.draw("hello.svg");
}

Tutorials

The tutorials are not available online yet. They can be found in the tutorials directory inside the zip file.

Documentation

The documentation is available online here.
It can also be found in the documentation directory inside the zip file.

Changelog

rev 29 (27 - December - 2009):
  • Add methods for getting the intersecting points between shapes RShape.getIntersections(RShape other).
  • Improve the binary operations so that they are potentially faster (haven't tested yet) and mantain the style of the first shape.
rev 28 (28 - May - 2009):
  • Fix bug of lacking vertex in RG.beginShape()/RG.endShape().
  • Fix error string bug.
  • Again thanks to Florain Jenett and his students for spotting these.
rev 27 (18 - May - 2009):
  • New documentation build system. Thanks to Florian Jenett for the tips, script and stylesheets.
  • Small fix to a regression introduced in the last revision about the sizes of ellipses in SVG.
rev 26 (15 - May - 2009):
  • Added a fix to RG.polygonize(myShape) when myShape had no root level paths. Patch provided by Florian Jenett.
  • Fix binary operations of shapes. Now Tutorial 17 should work correctly.
  • Modified RG.getEllipse(x, y, w, h) to take width and height as arguments to be consistent with Processing's API.
  • Added RG.getRect(x, y, w, h). This returns a rectangle in the form of a RShape.
  • Added RG.getRing(x, y, widthBig, widthSmall). This returns a ring in the form of a RShape.
  • Added RG.getStar(x, y, widthBig, widthSmall, spikes). This returns a star in the form of a RShape.
rev 25 (4 - March - 2009):
  • Modified the behaviour of RG.shape(myShape, x, y, w, h) to match that of Processing's PShape in order to avoid confusion. If you want the shape to fit in the rect defined by x, y, w and h, use myShape.transform(x, y, w, h).
rev 24 (3 - March - 2009):
  • Added the method RG.createShape(RPoint[][] points) for easy building shapes from arrays of point arrays.
rev 23 (3 - March - 2009):
  • Added the so needed getChild(String target) method to RShape. This method returns an RShape whose id mathces target or null if no match has been found.
rev 22 (25 - February - 2009):
  • Removed obsolete tutorials and fixed some that were broken.
  • Fixed the PDF output so it is not tesselated (when it can it uses the breakShape() method of the backend). PDF is still tesselated when using beginRecord()/endRecord() in backends that don't support breakShape() such as OPENGL, P3D and P2D. In those cases createGraphics() should be used. Look at the Tutorial about SVG to PDF to see how.
rev 21 (19 - February - 2009):
  • Added the methods .scale(s, p), .scale(s, x, y), .scale(sx, sy, p) and .scale(sx, sy, x, y) to allow scaling relative to a given point.
  • Fix the .getArea() method. It is now calculated using the points of the curve and not the handles and it will not return negative values.
rev 20 (14 - February - 2009):
  • Added the methods .contains(shp), .containsBounds(shp), .containsHandles(shp) and .intersects(shp), .intersectsBounds(shp), .intersectsHandles(shp) to all geometric elements.
rev 19 (29 - November - 2008):
  • Added the methods .getX and .getY() to all geometric elements. This should finally deprecate the use of .getBounds()
rev 18 (26 - November - 2008):
  • Major addition of a RG static class that contains most functions available in the library and that resembles more to the Processing way of doing things (RG.loadShape(), RG.loadFont(), RG.beginShape(),...).
  • Updated the examples to use the new RG interface.
  • Renamed RGeomerative.init() -> RG.init()
  • Changed the way getBounds() works. It now returns an instance of type RRectangle.
  • RGroup will soon become deprecated. Please start using RShape everywhere and it's method children. This will allow us a smoother transition to Processing's PShape.
rev 15 (06 - October - 2008):
  • Major bug fixes
  • Renamed RSubshape -> RPath
  • Renamed getPoints -> getHandles
  • Renamed getCurvePoints -> getPoints
  • Added method getHeight returns the height of a geometric element
  • Added method getWidth returns the width of a geometric element
  • Added method transform rescales the geometric element to fit a rectangle
  • Added method contains takes as input an RPoint returns True if inside the geometric element False otherwise
  • Added method split returns an array of RGroup containing the two geometric elements resulting in splitting the geometric element at the advancement passed as input
  • Added method splitPaths returns an array of RGroup containing the two geometric elements resulting in splitting each of the paths of the geometric element at the advancement passed as input
  • Added method insertHandle inserts a new handle in the geometric element at the advancement passed as input
  • Added method insertHandleInPaths inserts a new handle in each of the paths of the geometric element at the advancement passed as input
  • Added method getPointsInPaths returns an array of arrays of RPoint for the point on each of the paths of the geometric element
  • Added method getHandlesInPaths returns an array of arrays of RPoint for the handle on each of the paths of the geometric element
  • Added method getTangentsInPaths returns an array of arrays of RPoint for the tangent on each of the paths of the geometric element
  • Mark Luffel made the clipping (used for the binary operations and for rendering in OPENGL) faster and better
  • Mark Luffel made the buildsystem using Makefile
rev 12 (05 - May - 2008):
  • Partial support for SVG styles
  • Fixes in SVG commands: line, polyline, path, etc...
rev 11 (28 - April - 2008):
  • Partial support for SVG transformations
  • Partial support for SVG commands: line, polyline, path, etc...
  • Introduction of RGeomerative.init(PApplet applet)