zaterdag 7 november 2015

Scripting vector graphics with iPath

Since a while I've been creating a language (or DSL) in Javascript for scripting designs, images, contours etc. I called it iPath and it's used in my website StretchSketch.

Originally iPath is intended for creating cnc files. The idea was to create customisable templates, which can be cut by cnc devices like routers, lasercutter or watercutters. At first I thought that SVG was the lingua franca for vectorised graphics but this is only true in the world of internet (browsers). CNC shops still hold to their good old DXF. Converting SVG to DXF turned out to be less straightforward than anticipated. Inkscape did do a poor job (at that time), and other solutions where costly. So I decided to make iPath format agnostic. Currently it can generate SVG and DXF but theoretically other generators can be used as well.

In iPath one can formulate a 2D drawing by instantiating a new iPath and calling methods on it in a way known as a fluent interface. A square can be formed by the following snippet:

var square = new iPath().line(20,0).line(0,20).line(-20,0).line(0,-20);

A line takes 2 arguments an x and y coordinate, so above will generate a square with a length of 20.

var l = 30;
var square = new iPath().line(l,0).line(0,l).line(-l,0).line(0,-l);

This will create a square with a length of 30 but its easier to adapt its dimension. So far we've only been creating the model, we can't show the model yet. If we want to display the square as SVG (as the path's d-attribute) we need to call dPath(significance).

<path id="s3" d="M 0 0"/>
..
document.getElementById("s3").setAttribute('d', "M 10 10" + square.dPath(3));

iPath's lines, moves etc are all relative: every movement is measured from the pen's current position. The only time absolute coordinates are needed, is for positioning your iPath model. In SVG path capitalised Characters means absolute parameters, and this is exactly what the "M 10 10" means: go to (10,10) in your current view).

So far we've only been looking at x,y coordinates (Cartesian), but we can also use polar coordinates. In this case we need to give an angle and distance as argument. Seasoned programmers may remember turtle graphics, part of the logo programming language, and iPath borrows this for indicating cartesian lines. The argument for turtleLine is an object with the angle (a) an distance (r) as properties. When repeated it is possible to create circular figures.

var gear = {};
gear.n = 20;
gear.r=100;
gear.h=0.7;

gear.ribbon = gear.r * Math.sin(Math.PI/gear.n) * 2 ;
gear.toothAngle = Math.atan(2* gear.h, gear.ribbon);
gear.toothSide = gear.ribbon / (2*Math.cos(gear.toothAngle));
gear.iPath = new iPath().turtleLine({a: (2*Math.PI / gear.n) - gear.toothAngle, r: gear.toothSide})
       .turtleLine({a: 2*gear.toothAngle, r: gear.toothSide}).turtleLine({a:-gear.toothAngle})
       .repeat(gear.n);

This will create a gear:

Feel free to experiment with the customizable gear.

As stated earlier iPath has been created for CNC applications, one of the features is to generate dxf alongside to SVG. This possiblity lets you adapt and view interactively SVG designs in the browser. Once a design is completely to your liking, it can be generated in DXF. Generating DXF is not as simple as it is for SVG, paths are not enough. DXF only comes in complete files and needs to be organized in layers. It is advised to use one layer per iPath model.

dxfBuilder = new DxfBuilder(new Blobber(), 3);
      gear.iPath.dxf(dxfBuilder,{layer: {name: 'jeroen', layer_color: 6}});
      saveAs(dxfBuilder.getBlob(), gear.filename);

saveAs is from Eli Grey's FileSaver. The DxfBuilder is from iPath's DXF library.

iPath's can be concatenated with concat:

new iPath().line(20,20).concat(new iPath().line(-20,40));

zondag 20 februari 2011

chrome search engines

I've switched for quite some time now to chrome. However one oddity remained with chrome after I came back from holiday in Turkey: entering search terms in the address / search bar would lead me to the turkish google site, displaying turkish sites first, and all google information in Turkish.

I do like Turkish pizza, and I wish good health and good fortune to the Turkish people and I even don't mind when the Turkish become member of the European Union but having my search results in Turkish is just over the edge. This is where my love for Turkey stops.

Problem was to change this behavior I tried setting locale, but nothing was wrong with that (or maybe resetting did not solve it).
Until half an hour ago: I found the search engine option under the manage key at the basic preference panel. There I could not edit the default google search engine, so I tried to add an entry, but I found no way to add that entry to the default search engine part. I then removed google but alas I was not able to restore that leaving me only with bing or yahoo as a valid option.

I tried reinstalling chrome: to no avail as the user data settings are not updated. Removing the whole user data setting part (under ~/Library/Application Support/Google/Chrome/Default) Did solve my problem but that also removed all my local settings. Only removing the Web Data file was the accurate and spot on solution. This appears to be a sqlite datafile so I may be able to change it from there, but chrome is just capable of restoring this file to its original state and that solved my issue.

woensdag 19 januari 2011

file api with jquery

I have been working on a pure html website last year called iscriptdesign. It focuses on parameterized design with svg. Templates with svg and javascript code are processed, so that the user input gets evaluated by embedded javascript producing the svg. The svg can be exported, and you can use the output for a laser cutter or water cutter. Check it out ! One of the major shortcomings is the fact that it is not easy to display templates yourself. I was not able to load the template contents by a file uri, and so I had to rely on the templates on the same server as the html/javascript code for iscriptdesign resided. In the back of my mind I was looking for a more cms like approach to allow for personal uploads from third parties.

Until recently I started to realize the possibilities of the html5 file api. How sweet would it be if people could just drag n drop a template from their local filesystem on a drop spot of iscriptesign? Yesterday I started working on the project and now it's finished.

One of the real challenges was to incorporate it in jquery. Okay not really necessary of course but having the greater part of my website in jquery does make it somewhat desirable and you overtyping an example is not challenging is it?
help from stackoverflow and javaranch gave me head start (now that is challenging).

code



jQuery.fn.initDrop = function() {
return this.each(function () {
$(this).bind("dragover", function () {$(this).addClass('focus');$(".drop_container").addClass('focus'); return false;});
$(this).bind("dragleave",function () { $(this).removeClass('focus');$(".drop_container").removeClass('focus'); return false;});
$(this).bind("drop",function(e) {
$(".focus").removeClass("focus");
$(".drop_container").addClass('focus');
e.preventDefault();
var file = e.originalEvent.dataTransfer.files[0];
var reader = new FileReader();
reader.onload = function (evt) {
digestRaw(evt.target.result, true);
};
reader.readAsText(file);
});
$(this).prepend('
');
});
};


The div label dropspot is a simple div tag.

<div class="dropspot" id="dropspot">Drop Spot</div>

Which gets its drop behavior by:

$("#dropspot").initDrop();


Lessons


  • Unfortunately I only found this working for Firefox (Mac and Windows) and Chrome (Mac, Windows not tested). Safari is not supporting this yet.

  • dropevent needs to be unwrapped by retrieving e.orginalevent.

  • dragend is not working should be dragleave.

  • In my case i need to remove linefeed/carriage return characters for windows(msdos) files I need to do a text.replace("result.replace(/\r\n?|\n/g, "");


donderdag 2 juli 2009

Eclipse galileo

Just installed Eclipse Galileo the latest and gratest as I type.
with some quirks.
I need to set the proxy, by default it sets it to a native active provider, I had to change it to a manual "active provider".
Installation of subversive from polarion went fine allthough I forgot to add connectors
(available from http://community.polarion.com/projects/subversive/download/eclipse/2.0/galileo-site)
m2eclipse for maven support (http://m2eclipse.sonatype.org/update, exclude subclipse handler optional,and maven project configurators.
spring ide (http://springide.org/updatesite)

Than I run into a
Get repository folder children operation failed.
svn: OPTIONS of '/svn/restofurl': 500 Server Error (http://serverrr.itc.intranet:8083)
svn: OPTIONS request failed on '/svn/restofurl'

Error, which was solved by adding the serverrr.itc.intranet to the list of "bypass from proxy" in the proxy pane in the preferences

woensdag 4 februari 2009

mvn create artifacts

Just played around with the wicket quickstart.
all well and fun however importing it in eclipse is not making it a web project.
for eclipse ganymede, mvn eclipse:eclipse -Dwtpversion=2.0 worked almost.
It still gives an error in eclipse: Java compiler level does not match the version of the installed Java project facet. Unknown Faceted Project Problem (Java Version Mismatch) I fixed that by 1: in the compiler properties downgrading to java version 1.4, and than in projects facets setting the java version back to 5.0
et voila!

zondag 7 december 2008

mysql with launchd

Just tried to install mysql on ox leopard. Instead of the documented 'MySQL Startup Item' I've chosen to go the mac road: launchd, as I understand mac's equivalent of windows services. It's something unique to mac and apparantly very flexible, check it out.


Mysql installs fine from the pkg distribution, however it gets installed under root:wheel.
bringing the file: com.mysql.mysqld.plist in /Library/LaunchDaemons/com.mysql.mysqld.plist will make it automatically pick it up during startup, you may manually control it by sudo launchctl (un)load com.mysql.mysqld.plist.



starting mysql under the user mysql. However logging to mysql to change the password: mysqladmin -u root password 'secret' fails with the message:

error: 'Access denied for user 'root'@'localhost' (using password: NO)'


I've not been able to solve the problem, the documentation failes on this point. I could not manually start mysqld because, it was installed under root:wheel. So the only way to get it right: reinstall it, chmod -R jeroen:admin /usr/local/mysql*.
Than do the mysqladmin -u root password 'secret'. After that update the com.mysql.mysqld.plist file to jeroen/admin for group/userid.
Hopefully this works

zaterdag 22 november 2008

motor in de garage.

Ik heb een motor en die staat mooi en droog in de garage. Alleen als ik de motor eruit wil halen ben ik enorm aan sleuren en trekken. Niet heel erg handig. Vanochtend heb ik een plateau gemaakt van de aanrechtbladen die eerder vervangen zijn (niet alles meteen weggooien), en 3 kleine transport-tableautjes verkrijgbaar bij de praxis voor 10 euro per stuk. Ik was bang dat 60 cm niet genoeg zou zijn om de motor op zijn standaard te laten staan, en heb dus een plateautje wat laten uitsteken, was achteraf niet nodig. Goed om je te realiseren dat het tableau erg beweeglijk is op het moment dat je de motor erop rijdt, veranker het aan de voor- en achterkant. Als de motor er eenmaal opstaat en je versnelt zal het plateau veel sneller wegschieten dan de motor (wet van impuls denk ik). Zorg ook bij wegrijden dat het tableau aan de achterkant gezekerd is.