Wednesday, May 29, 2013

That's a Wrap

Dear reader,
I am wrapping up this blog as I am preparing to print and bind it. There are a lot of loose threads, "I will post about"s, and a distinct lack of closure. Fractal Canvas has most of its features and most of its design, but hasn't been published, tested, and revised in full-form yet.

The process of developing Fractal Canvas has been fun, challenging, and instructional. My primary growth in reflecting on that learning process in this blog has been learning how to communicate my projects to a general audience in a varied, interesting, general voice. I hope you have enjoyed reading this blog, and maybe some day you can check out www.fractalcanvas.com again and see what it becomes.

Istvan.

Elite Athletes Listen To Their Coaches

An article about Olympic athletes and their relationships with their coaches, this Huff Post piece outlines the importance of listening to advice and why, sometimes, we might not accept it so easily. Students were asked to consider this in terms of their relationships with their teachers.

An interesting trait shared by the best teachers I have ever had is they recognize what I do outside of class and have a reasonable idea of how their class fits in. A teacher who is fully involved in their subject may produce high test scores, but not necessarily well-rounded students.

A good coach, on the other hand, is hired to perfect one skill (gymnastics for example). To this extent, coaches and teachers are not similar.

Both do give advice and criticism, however. Being receptive to that feedback is important in both cases, and often difficult in both cases. Especially in my project where I wanted to incorporate user feedback into my site, the difference between criticism on how the site works vs. how they expect it to work is very different from criticism on my process. The former is easy to receive for me, the latter takes cogitation.

There isn't really a "moral" to this post, it's just some observations for consideration.
Istvan.

Logistics Explained

I met with Mr. Drix to have him explain what is going on with the logistic graph featured in the logistic app. He explained it using several representations, some of which I want to add to my long-term goals to implement (after WISE), including the Feigenbaum plot. I have written up the fruits of our conversation and will be publishing it live to fractalcanvas.com after proofing it and finding diagrams.

Istvan.

Sunday, May 26, 2013

Statistics

SAFE, the framework/compiler I'm using, has a feature that tells you how much code is on your site. Prepare to have your mind blown.

specified SFW lines: 448 (The basics for the page with no content (including sidebar, login, etc. just the page)

generated SFW lines: 2184 (The framework takes the above SFW lines and generates the live code of this length)

specified CSS lines: 2174 (Including the base style that comes with the framework, this is how many lines of styling code there are on the site)

specified JS lines: 23163 (Including the libraries included in the framework, this is how many lines of JavaScript are on my site)

I might modify the statistics code to tell me how much of those last two pieces I wrote. Stay posted!

Saturday, May 25, 2013

Fractal Engine

The last time I posted a sample of code it was hugely popular - so I'm doing it again. This time, it is the backbone of the FractalCanvas program - the Fractal Engine. The code is a little bit more complex than anything I have posted thus far, so cling to the red comments which explain what is going on!
Note: this code is not yet optimized - by storing some values instead of calculating them multiple times and by algebraically simplifying some operations I anticipate this code running far more quicklky and effeciently than it does.


//fractalCanvasEngine provides tools to generate and manipulate fractals
function fractalCanvasEngine() {
//transpose is a function to scale and move the points in a fractal so that the first point is on (0,0) and the last point is on (1, 0)
this.transpose = function(sketchPoints){
  var transposedSketchPoints = [], angle, length, pointAngle, pointLength, i;
  
  //calculates the length of the line connecting the first and last points
  length = Math.sqrt(Math.pow(sketchPoints[0][1] - sketchPoints[sketchPoints.length - 1][1], 2) + Math.pow(sketchPoints[0][2] - sketchPoints[sketchPoints.length - 1][2], 2));
  //calculates the angle of the line connecting the first and last points
angle = Math.asin((sketchPoints[0][2] - sketchPoints[sketchPoints.length - 1][2]) / length);
  //for each point in the fractal apply the rotation and scaling
for(i = 0; i < sketchPoints.length; i++){
   pointLength = Math.sqrt(Math.pow(sketchPoints[0][1] - sketchPoints[i][1], 2) + Math.pow(sketchPoints[0][2] - sketchPoints[i][2], 2));
   pointAngle = Math.asin((sketchPoints[0][2] - sketchPoints[i][2]) / pointLength) - angle;
   
   //Add the newly transformed point to the output array
   transposedSketchPoints.push([
    sketchPoints[i][0],
    Math.cos(pointAngle) * pointLength / length || 0,
    Math.sin(pointAngle) * pointLength * -1 / length || 0
   ]);
  }
  return transposedSketchPoints;
 }

 //scale takes a fractal and rescales it to fit in a 1 by 1 window
 this.scale = function(points){
  var minX = points[0][1] || 0,
  maxX = points[0][1] || 0,
  minY = points[0][2] || 0,
  maxY = points[0][2] || 0,
  scaleFactor, point;
  
  //find the size of the fractal (height and width)
  for(point in points){
   if(points[point][1] < minX) minX = points[point][1];
   if(points[point][1] > maxX) maxX = points[point][1];
   
   if(points[point][2] < minY) minY = points[point][2];
   if(points[point][2] > maxY) maxY = points[point][2];
  }
  
  //calculate how much the fractal needs to be scaled
  scaleFactor = Math.min(1 / (maxX - minX), 1 / (maxY - minY));
  
  //apply the scaling to each of the points
  for(point in points){
   points[point][1] -= minX;
   points[point][1] *= scaleFactor;
   
   points[point][2] -= minY;
   points[point][2] *= scaleFactor;
  }
  
  return points;
 }

 //the heart of the fractal engine - a recursive function that generates the fractal
 this.getLevel = function(remainingLevels, points)
 {
  //continue recursive operation, there are more levels to calculate
  if(remainingLevels > 0){
   var subLevel = this.getLevel(remainingLevels - 1, points),
   prevPoint,
   curPoint,
   rotFactor,
   scaleFactor,
   returnLevel = new Array(),
   subRot,
   subScale,
   i,
   inverse;
   
   for(i = 1; i < points.length; i++){
    prevPoint = points[i-1];
    curPoint = points[i];
    
    if(curPoint[0] === 1 || curPoint[0] === 2){
     //this is where the actual fractal is generated... its fairly complex. In short, it converts the fractal to polar, applies the transformations (including flipping it if necessary) and then converts it back to rectangular. I am not going to try to explain where/how all of that happens.
     scaleFactor = Math.sqrt(
      Math.pow((curPoint[2]-prevPoint[2]), 2)
      + Math.pow((curPoint[1]-prevPoint[1]), 2)
     );
     rotFactor = Math.asin((curPoint[2]-prevPoint[2])/scaleFactor);
     
     inverse = (curPoint[0] === 1 ? 1 : -1);
     
     for(var j = 0; j < subLevel.length; j++){
      subScale = Math.sqrt(Math.pow(subLevel[j][2], 2) + Math.pow(subLevel[j][1], 2));
      
      subRot = Math.asin((subLevel[j][2]/subScale) || 0);
      if(subLevel[j][1] < 0) subRot += (Math.PI/2 - subRot)*2;
      
      returnLevel.push(Array(subLevel[j][0],
       ((subScale)*scaleFactor)*Math.cos(rotFactor+inverse*subRot)+prevPoint[1],
       ((subScale)*scaleFactor)*Math.sin(rotFactor+inverse*subRot)+prevPoint[2]));
     }
    }
    else returnLevel.push(Array(curPoint[0], curPoint[1], curPoint[2])); //the type of this segment is not one that requires it to be replaced by a fractal
   }
   return returnLevel;
  }
  else return [[1, 0, 0], [1, 1, 0]]; //level 0 is just a line
 }
}
var fractalCanvasEngine = new fractalCanvasEngine();

Sample Presentation

Luke's fantastic sample presentation brought a couple of points to my attention. Luke's powerpoint was very well done; the text was sparse and concise, images relevant and aided his explanations, and the entire presentation was well organized. The part that struck me as the most impressive was Luke's ability to answer questions - whether an obscure history question, or a technical playing question. His research and understanding were evident.

The presentation also served as a good kick to start seriously thinking about my own project and my readiness.

Istvan.

Uh-oh

I updated the framework in hopes of using a new feature. Unfortunately there is some incompatibility/bug that is causing about half of the style to not appear - ie there is no sidebar and much of the functionality is broken. I am working with the developers of the framework to find the source of that bug now...

Stay posted.