Extending anar+

If your are familiar with JAVA object oriented structure, you won't be surprised to see that you could extend classes in anar+. Extending anar+ classes is useful when you want to create a special type of point, lines, faces, objects, transformation or parameter while preserving the geometric associativity (parametric structure). anar+ is meant to be extended from the basic primitives. Here, we present a simple example how to do it. The process outline how to implement a build() method within your newly extended class.

Extending Param class

Sometimes you will need more complex calculations than what you have built-in anar+. Since almost everything in anar+ is associative, you might need to create a complex calculation that will be also parametric. Param are similar to floats in java. They hold a value which is based on parent object. We will describe the basic mechanism to create your own Param. Let's we want a function such as atan2 and you couldn't find it in the documentation.

Let's say we want something similar to atan2() http://processing.org/reference/atan2_.html in processing. There's no ParamAtan2, but let's create one.

First let's create a new class extending anar.Param:

class ParamAtan2 extends Param {
  
  ParamAtan2(){
    //Constructor
  }
  
  @Override
  protected void build() {
    value = 0;
  }
  
}

* Note, if you are in Eclipse or plain JAVA, you might need (public) class ParamAtan2 extends Param in front of your declaration and the required java libraries (import).

This is the basic class. You have here a constructor for your ParamAtan2 and a method build() that will be called each time a parent is modified. This is the simpliest structure. Here, our class won't do anything, except reseting the value to 0 each time parent are modified. In this case we don't have any parent.

Let's declare some parents in the constructor:

  Pt myInternalPt;
  
  ParamAtan2(Pt myPt){
    addParent(myPt);//This is how you declare you parents
          //parents could only be Parametric:
          //Param,Pt,Pts,Face,Obj,Group,Transform
    myInternalPt = myPt;
  }

Then, we could write the build() method telling what operation to perform:

  protected void build() {
    float x = myInternalPt.x();
    float y = myInternalPt.y();
    value = (float)Math.atan2(x,y);
  }

Note that we need to convert the value in float as Math.atan2(x,y); in java returns a double.

We then have already a parametric object returning a value based on atan2 for a point. If the given point (the parent) is updated, build() is called and the new value for the ParamAtan2 is also updated with the new values.

It's prefered for the build() methods to keep the things fast as possible, since it could be used massively and linked inside many objects. It's also good to avoid the creation of Parametric objects (Param, Pt, Pts, Face, Obj, Group, Transform) inside build to reduce the memory foot print. If you need Parametric objects, reusing objects will be prefered.

Alternatively for the build() method you could also say:

  protected void build() {
    Pt p = (Pt)parent.get(0);
    float x = myInternalPt.x();
    float y = myInternalPt.y();
    value = (float)Math.atan2(x,y);
  }

You should only be aware of what you added first, and to cast the object back into the desired object (Pt). Usually, it is easier to maintain your own list of objects that you will use to create your Param.

Here is the complete result for the ParamAtan2 class:

public class ParamAtan2 extends Param {
  
  Pt myInternalPt;
  
  ParamAtan2(Pt myPt){
    addParent(myPt);
    myInternalPt = myPt;
  }
  
  protected void build() {
    float x = myInternalPt.x();
    float y = myInternalPt.y();
    value = (float)Math.atan2(x,y);
  }
  
}

And here is an example of use of the class:

Pt someWhere = Pt.create(100,200,0);
    Param value = new ParamAtan2(someWhere);
    Anar.sliders(value);

Extending Pt

Here we present a more geometrical example where we extend a point. We must first declare in the constructor which are the parent objects (here, it's two existing points). In build method, we describe the relationship between those objects. build() is internally called each time either parent a or b is modified. The propagation of changes is done behind, all you need to implement (express) is the relation between those objects and how to construt the desired form.

public class PtMid extends Pt{
 
  //Constructor from two existing parents points
  public PtMid(Pt a, Pt b){
    addParent(a);
    addParent(b);
  }
 
  //build() is called each time a parent is changed.
  //    This is how the parametric behavior is achieved.
  //    build() method express the relationShip between obj1 and obj2. This might be seen as the place where you express the intrinsic properties of a construction.
  @Override protected void build(){
    Pt a = ((Pt)parent.get(0));
    Pt b = ((Pt)parent.get(1));
 
    x = ( (b.x()-a.x())/2)+a.x();
    y = ( (b.y()-a.y())/2)+a.y();
    z = ( (b.z()-a.z())/2)+a.z();
 
    super.build();
  }
}

Observe that in the parent list, you could store any following anar+ primitive (param,pt,pts,face,obj). You can get them back (in the build() method through parent.get(i). Note that you need to cast your object in the right type.

Note that you could have many constructors.

  //Constructor from a sett of coordinates
  public PtMid(float x1, float y1, float x2, float y2){
    //You then first need to create your parents
    Pt a = new Pt(x1,y1);
    Pt b = new Pt(x2,y2);
 
    //Then, it's simliar to the previous example.
    addParent(a);
    addParent(b);
  }

In the next case, we will create object fields. If you prefer (I think it's a matter of taste), there's a second way to do it. The next is example is slightly different form the first one, it uses the inner explicit fields inside your object.

public class PtMid extends Pt{
 
  Pt a;  //Parent 1
  Pt b;  //Parent 2
 
  //Constructor from two existing parents points
  public PtMid(Pt a, Pt b){
    this.a = a;    //Note, it is similar to previous method, but here, we explicitly create a field four our parents.
    this.b = b;
    addParent(a);  //You still need to add your object to parent list
    addParent(b);
  }
 
  //build() is called each time a parent is changed.
  //    This is how the parametric behavior is achieved.
  //    build() method express the relationShip between obj1 and obj2. This might be seen as the place where you express the intrinsic properties of a construction.
  @Override protected void build(){
    x = ( (b.x()-a.x())/2)+a.x();
    y = ( (b.y()-a.y())/2)+a.y();
    z = ( (b.z()-a.z())/2)+a.z();
    super.build();
  }
}

Of course, you could give any name to your object. Usually, we name the object with the corresponding primitive (aka PtSomething for points).

Extending Renders

In anar+, we separated geometry and representation of an object. For every anar+ primitives, we have a two fields that might be override in order to display differently on screen. A lot might be done by extending renders, but it doesn't affect the geometry itself. In the next example, we show how to change how points are displayed.

import anar.geo.*;
import anar.render.RenderPt; //You need to extend on of the abstract classes
                             //for each chosen primitive. At least you need
                             //**anar.render.RenderP5** which is the most abstract
                             //render class. You might override RenderP5 for
                             //something else such as direct JOGL calls (immutable
                             //forms).
 
public class RenderPtCross extends RenderPt {
 
  public float size = 1f; //Set simply the length of each edges displayed.
 
  public RenderPtCross(float i){
    size = i;
  }
 
  //draw() is the method to re implement. You'll receive the desired object and you
           use p5 (which is like being in processing) and you find a way to draw it.
  @Override
  public void draw(Pt p){
    p5.line(p.x()-size,p.y(),p.z(),p.x()+size,p.y(),p.z());
    p5.line(p.x(),p.y()-size,p.z(),p.x(),p.y()+size,p.z());
    p5.line(p.x(),p.y(),p.z()-size,p.x(),p.y(),p.z()+size);
  }
}