topical media & game development

talk show tell print

lib-of-vs-addons-ofxVectorGraphics-src-ofxVectorGraphics.cpp / cpp



  include <ofxVectorGraphics.h>
  
  //we need a point class that can actually be used
  //scroll down for the vectorGraphics code
  class ofPoint3 : public ofPoint{
  
          public:
                  ofPoint3(float _x = 0, float _y = 0, float _z = 0){
                          x = _x;
                          y = _y;
                          z = _z;
                  }
  
                  void set(ofPoint3 &p){
                          x = p.x;
                          y = p.y;
                          z = p.z;
                  }
                  
                  void set(float _x, float _y){
                          x = _x;
                          y = _y;
                  }
                  
                  void set(float _x, float _y, float _z){
                          x = _x;
                          y = _y;
                          z = _z;
                  }                
                                  
                  bool operator==(const ofPoint3 &p) { 
                          return (x == p.x) && (y == p.y) && (z == p.z);
                  }
  
                  bool operator!=(const ofPoint3 &p) { 
                          return (x != p.x) || (y != p.y) || (z != p.z);
                  }
      
                  ofPoint3 operator+(const ofPoint3 &p) const { 
                          return ofPoint3( x+p.x, y+p.y, z+p.z); 
                  } 
                  
                  ofPoint3 operator+(const float f) const { 
                          return ofPoint3( x+f, y+f, z+f );
                  } 
                  
                  ofPoint3& operator+=(const ofPoint3& p) { 
                          x += p.x;
                          y += p.y;
                          z += p.z;
                          return *this; 
                  } 
      
                  ofPoint3& operator+=(const float f) { 
                          x += f;
                          y += f;
                          z += f;
                          return *this; 
                  }         
          
                  ofPoint3 operator-(const ofPoint3 &p) const { 
                          return ofPoint3( x-p.x, y-p.y, z-p.z ); 
                  } 
                  
                  ofPoint3 operator-(const float f) const { 
                          return ofPoint3( x-f, y-f, z-f );
                  } 
                  
                  ofPoint3& operator-=(const ofPoint3 &p) { 
                          x -= p.x;
                          y -= p.y;
                          z -= p.z;
                          return *this; 
                  } 
  
                  ofPoint3& operator-=(const float f) { 
                          x -= f;
                          y -= f;
                          z -= f;
                          return *this; 
                  }                 
  
                  ofPoint3 operator-() const { 
                          return ofPoint3( -x, -y, -z ); 
                  }
                  
                  ofPoint3 operator*(const ofPoint3 &p) const { 
                          return ofPoint3( x*p.x, y*p.y, z*p.z ); 
                  } 
                          
                  ofPoint3& operator*=(const ofPoint3 &p) { 
                          x *= p.x;
                          y *= p.y;
                          z *= p.z;
                          return *this; 
                  } 
  
                  ofPoint3 operator*(const float f) const { 
                          return ofPoint3( x*f, y*f, z*f );
                  } 
                  
                  ofPoint3& operator*=(const float f) { 
                          x *= f;
                          y *= f;
                          z *= f;
                          return *this; 
                  } 
                  
                  ofPoint3 operator/(const ofPoint3 &p) const { 
                          return ofPoint3( x/p.x, y/p.y, z/p.z );
                  } 
                  
                  ofPoint3& operator/=(const ofPoint3 &p) { 
                          x /= p.x;
                          y /= p.y;
                          z /= p.z;
                          return *this; 
                  } 
  
                  ofPoint3 operator/(const float f) const { 
                          return ofPoint3( x/f, y/f, z/f );
                  } 
  
                  ofPoint3& operator/=(const float f) { 
                          x /= f;
                          y /= f;
                          z /= f;
                          return *this; 
                  }
  
          union{
                  struct{
                  float x; 
                  float y;
                  float z;};
                  float v[3];
          };
          
  };
  
  //----------------------------------------------------------                        
  ofxVectorGraphics::ofxVectorGraphics(){
          bDraw                = true;
          bFill                = true;
          bCenter                = false;
          bRecord                = false;        
          bFirstPoint = false;        
          bShouldClose= false;
          whichShapeMode = 0;                
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::beginEPS(string fileName, int x, int y, int w, int h){
          creeps.newFile(ofToDataPath(fileName).c_str(), x, y, x+w, y+h);
          bRecord = true;
          
          //CreEPS uses lower left as (0,0)
          //so we have to flip our coordinates
          //this works fine as long
          //as the window doesn't change size 
          //while we are capturing!!!                                
          creeps.applyTranslation(0, ofGetHeight());
          creeps.applyScaling(1, -1);
  }
  
  //----------------------------------------------------------                                                
  void ofxVectorGraphics::endEPS(){
          creeps.resetTransformations();
          creeps.finalize();
          bRecord = false;
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::enableDraw(){ 
          bDraw = true; 
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::disableDraw(){ 
          bDraw = false; 
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::enableCenterRect(){ 
          bCenter = true; 
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::disableCenterRect(){ 
          bCenter = false; 
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::fill(){ 
          bFill = true; ofFill(); 
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::noFill(){ 
          bFill = false; ofNoFill();
  }
  
  //----------------------------------------------------------                        
  void ofxVectorGraphics::setLineWidth(float lineWidth){
          glLineWidth((int)lineWidth);
          if(bRecord) creeps.setAttributes( CAtLineThickness(lineWidth) );
  }
  
  //----------------------------------------------------------
  void ofxVectorGraphics::setColor(int _r, int _g, int _b){
          float r = (float)_r / 255.0f; r = MAX(0,MIN(r,1.0f));
          float g = (float)_g / 255.0f; g = MAX(0,MIN(g,1.0f));
          float b = (float)_b / 255.0f; b = MAX(0,MIN(b,1.0f));
          changeColor(r, g, b);
  }
  
  //----------------------------------------------------------
  void ofxVectorGraphics::setColor(int hexColor){
          int r = (hexColor >> 16) & 0xff;
          int g = (hexColor >> 8) & 0xff;
          int b = (hexColor >> 0) & 0xff;
          setColor(r,g,b);
  }
  
  //----------------------------------------------------------
  void ofxVectorGraphics::changeColor(float r, float g, float b){
          glColor3f(r,g,b);
          if(bRecord)creeps.setAttributes( CAtColor(r, g, b) );
  }
  
  //----------------------------------------------------------                
  void ofxVectorGraphics::rect(float x1,float y1, float w, float h){
          if(bDraw){
                  if(bCenter)ofSetRectMode(OF_RECTMODE_CENTER);
                  else ofSetRectMode(OF_RECTMODE_CORNER);
                  ofRect(x1, y1, w, h);
          }
          if(bRecord){
                  if(bCenter){
                          x1 -= w * 0.5;
                          y1 -= h * 0.5;
                  }
                  
                  if(bFill) creeps.rectFill(x1,  y1,  w,  h); 
                  else creeps.rectStroke(x1, y1, w, h);
          }
  }
  
  //----------------------------------------------------------
  void ofxVectorGraphics::triangle(float x1,float y1, float x2, float y2, float x3, float y3){
          if(bDraw){
                  ofTriangle(x1, y1,  x2,  y2,  x3,  y3);
          }
          if(bRecord){
                  creeps.startPath(x1, y1);
                  creeps.addLine(x2,  y2);
                  creeps.addLine(x3,  y3);                                                
                  creeps.closeSubpath();
                  if(bFill)creeps.endPath(CreEPS::FILL);
                  else creeps.endPath(CreEPS::STROKE);
          }
  }        
  
  //----------------------------------------------------------
  void ofxVectorGraphics::circle(float x1,float y1, float radius){
          if(bDraw){
                  ofCircle(x1, y1, radius);
          }
          if(bRecord){
                  if(bFill) creeps.disk(x1, y1, radius); 
                  else creeps.circle(x1, y1, radius);
          }
  }        
  
  //----------------------------------------------------------
  void ofxVectorGraphics::ellipse(float x1,float y1, float w, float h){
          if(bDraw){
                  ofEllipse(x1, y1, w, h);
          }
          if(bRecord){
                  if(bFill){
                          //there is no filled ellipse in non-path mode
                          creeps.startPath();
                          creeps.addEllipse(x1, y1, w, h);
                          creeps.endPath(CreEPS::FILL);
                  } 
                  else creeps.ellipse(x1, y1, w, h); 
          }
  }        
  
  //----------------------------------------------------------
  void ofxVectorGraphics::line(float x1,float y1, float x2, float y2){
          if(bDraw){
                  ofLine(x1, y1, x2, y2);
          }
          if(bRecord){
                  creeps.line(x1, y1, x2, y2);
          }
  }        
  
  //-----------------------------------------------------------
  void ofxVectorGraphics::arc(float x, float y, float radius, float offsetAngleDegrees, float internalAngleDegrees){
          if(bDraw){
                  //no openFrameworks arc command so we make a ghetto gl one
                  int                arcResolution = 20;
                  float        step  = ( DEG_TO_RAD * internalAngleDegrees) / (arcResolution - 1);
                  float        angle = DEG_TO_RAD * offsetAngleDegrees;
                          
                  float        xpos, ypos;
  
                  if(!bFill){
          
                          glBegin(GL_LINE_STRIP);
                                  for(int i = 0; i < arcResolution; i++){
                                          xpos        = cos(angle) * radius;
                                          ypos        = sin(angle) * radius; 
                                          glVertex2f(x + xpos, y + ypos);                                                
                                          angle += step;
                                  }
                          glEnd();
                  
                  }else{
                          glBegin(GL_TRIANGLE_STRIP);
                                  for(int i = 0; i < arcResolution; i++){
                                          xpos        = cos(angle) * radius;
                                          ypos        = sin(angle) * radius; 
                                          glVertex2f(x + xpos, y + ypos);                                                
                                          glVertex2f(x, y);                                                                                                                
                                          angle += step;
                                  }
                          glEnd();
                  }
          }
          if(bRecord){
                  
                  //creps works differently it likes to know absolute starting and ending angles
                  float startAngle = offsetAngleDegrees;
                  float endAngle   = startAngle + internalAngleDegrees;
                  
                  //it also only like to go from smaller to bigger in terms of rotation
                  if(startAngle > endAngle){
                          float tmp = endAngle;
                          endAngle = startAngle;
                          startAngle = tmp;
                  }
                  
                  if(bFill){
                          creeps.startPath(x, y);
                          creeps.addArc(x , y, radius, startAngle,  endAngle);
                          creeps.endPath(CreEPS::FILL);
                  }else{
                          creeps.arc(x , y, radius, startAngle,  endAngle);
                  }
                  
          }
  }
  
  //----------------------------------------------------------
  void ofxVectorGraphics::bezier(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){
          if(bDraw){
                  ofBezier(x1, y1, x2, y2, x3, y3, x4, y4);
          }
          if(bRecord){
                  if(bFill){
                          creeps.startPath(x1, y1);
                          creeps.addCurve(x2, y2, x3, y3, x4, y4);
                          creeps.addLine(x1, y1);        
                          creeps.endPath(CreEPS::FILL);
                  }
                  else creeps.curve(x1, y1, x2, y2, x3, y3, x4, y4);
          }
  }                                
  
  //----------------------------------------------------------
  void ofxVectorGraphics::curve(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){
          if(bDraw){
                  ofCurve(x1, y1, x2, y2, x3, y3, x4, y4);                                                
          }
          if(bRecord){
          
                  //we treat the catmull rom curve as a bezier 
                  //by finding the approrpriate control points 
                  //to make the same curve
                                                                                                          
                  //x1 y1 = p1
                  //x2 y2 = p2
                  //x3 y3 = p3
                  //x4 y4 = p4
                  
                  //control point at p2 is parallel 
                  //to the line defined by p3 - p1
                  
                  //control point at p3 is parallel
                  //to the line defined by p4 - p2
          
                  ofPoint3 p1(x1, y1);
                  ofPoint3 p2(x2, y2);
                  ofPoint3 p3(x3, y3);
                  ofPoint3 p4(x4, y4);
                  
                  //SUPER WEIRD MAGIC CONSTANT = 1/6 (this works 100% can someone explain it?)
                  ofPoint3 cp1 = p2 + ( p3 - p1 ) * (1.0/6);
                  ofPoint3 cp2 = p3 + ( p2 - p4 ) * (1.0/6);                                                
                                  
                  creeps.startPath(x2, y2);
                  creeps.addCurve( cp1.x, cp1.y, cp2.x, cp2.y, x3, y3);
                  
                  if(bFill){
                          creeps.addLine(x2, y2);        
                          creeps.endPath(CreEPS::FILL);
                  }else{
                          creeps.endPath(CreEPS::STROKE);
                  }
          }
  }        
  
  //----------------------------------------------------------                                                
  void ofxVectorGraphics::beginShape(){
          if(bDraw){
                  ofBeginShape();
          }
          if(bRecord){
                  bFirstPoint                = true;
                  bShouldClose        = false;
          }
  }
  
  //----------------------------------------------------------                                                
  void ofxVectorGraphics::polyVertex(float x, float y){
          if(bDraw){
                  ofVertex(x, y);
          }
          
          if(bRecord){
          
                  //clear curve vertices
                  if(whichShapeMode == 1){
                          clearAllVertices();        
                  }
  
                  whichShapeMode = 0;
                  
                  if(bFirstPoint){
                          creeps.startPath(x, y);
                          bFirstPoint = false;
                          bShouldClose = true;
                  }else{
                          creeps.addLine(x,y);
                  }
          }
  }
  
  //----------------------------------------------------------        
  //this takes three arguments as it is based off the idea that at least one 
  //inital polyVertex has already been set.                                         
  void ofxVectorGraphics::bezierVertex(float x1, float y1, float x2, float y2, float x3, float y3){
          if(bDraw){
                  ofBezierVertex(x1, y1, x2, y2, x3, y3);
          }
          if(bRecord){
                  
                  //clear curve vertices
                  if(whichShapeMode == 1){
                          clearAllVertices();        
                  }
                  
                  whichShapeMode = 2;                                        
                  
                  //we can only add a bezier curve if the curve
                  //has started with a polyVertex
                  //so as long as this is not the first point we add it
                  if(!bFirstPoint){
                          creeps.addCurve(x1, y1, x2, y2, x3, y3);
                  }
                  
          }
  }                        
  
  //----------------------------------------------------------                                                
  void ofxVectorGraphics::curveVertex(float x, float y){
          if(bDraw){
                  ofCurveVertex(x, y);
          }
          if(bRecord){
          
                  //if some points have already been created
                  //this could crash the app 
                  //so we close the current path to be safe
                  if(bShouldClose){
                          if(bFill) creeps.endPath(CreEPS::FILL);
                          else creeps.endPath(CreEPS::STROKE);
                  }
          
                  whichShapeMode = 1;
          
                  double* point = new double[2];
                  point[0] = x;
                  point[1] = y;
                  curvePts.push_back(point);
          }
  }
  
  //----------------------------------------------------------                                                
  void ofxVectorGraphics::endShape(bool bClose){
          if(bDraw){
                  ofEndShape(bClose);
          }
          if(bRecord){
                                                                                          
                  //catmull roms - we need at least 4 points to draw
                  if( whichShapeMode == 1 && curvePts.size() > 3){                                                                                                
                          
                          //we go through and we calculate the bezier of each 
                          //catmull rom curve - smart right? :)
                          for (int i = 1; i< curvePts.size()-2; i++) {
                                  
                                  ofPoint3 prevPt(        curvePts[i-1][0],        curvePts[i-1][1]);
                                  ofPoint3 startPt(curvePts[i][0],                curvePts[i][1]);                                                        
                                  ofPoint3 endPt(        curvePts[i+1][0],        curvePts[i+1][1]);
                                  ofPoint3 nextPt(        curvePts[i+2][0],        curvePts[i+2][1]);
                                  
                                  //SUPER WEIRD MAGIC CONSTANT = 1/6
                                  //Someone please explain this!!! 
                                  //It works and is 100% accurate but wtf!
                                  ofPoint3 cp1 = startPt + ( endPt - prevPt ) * (1.0/6);
                                  ofPoint3 cp2 = endPt + ( startPt - nextPt ) * (1.0/6);                                                
                                  
                                  //if this is the first line we are drawing 
                                  //we have to start the path at a location
                                  if( i == 1 ){
                                          creeps.startPath(startPt.x, startPt.y);
                                          bShouldClose = true;
                                  }
                                  
                                  creeps.addCurve( cp1.x, cp1.y, cp2.x, cp2.y, endPt.x, endPt.y);
                          }                                                
                  }
                  
                  if(bShouldClose){                                                                                                                
                          //we close the path if requested
                          if(bClose)creeps.closeSubpath();
                  
                          //render the stroke as either a fill or a stroke.
                          if(bFill){
                                  creeps.endPath(CreEPS::FILL);
                          }else{
                                  creeps.endPath(CreEPS::STROKE);
                          }
                          bShouldClose = false;
                  }
                  
                  //we want to clear all the vertices
                  //otherwise we keep adding points from
                  //the previous file - cool but not what we want!
                  clearAllVertices();
                  
          }
  }                        
  
  //----------------------------------------------------------
  void ofxVectorGraphics::clearAllVertices(){
          for(vector<double*>::iterator itr=curvePts.begin();
                  itr!=curvePts.end();
                  ++itr){
                  delete [] (*itr);
          }
          curvePts.clear();
  }                        
                                                  
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.