jscad / OpenJSCAD.org

JSCAD is an open source set of modular, browser and command line tools for creating parametric 2D and 3D designs with JavaScript code. It provides a quick, precise and reproducible method for generating 3D models, and is especially useful for 3D printing applications.
https://openjscad.xyz/
MIT License
2.64k stars 513 forks source link

scad to jscad conversion fails #246

Closed Ognian closed 7 years ago

Ognian commented 7 years ago

Trying to use http://www.thingiverse.com/thing:1933779/#files with

node_modules/.bin/openjscad -v ESP8266_based_modules_models_library/files/ESP8266Models.scad -o ESP8266Models.jscad

I get:

OpenJSCAD 0.5.2 [Darwin:16.5.0,darwin:x64]
OpenSCAD Compatibility (0.5.2)
converting ESP8266_based_modules_models_library/files/ESP8266Models.scad -> ESP8266Models.jscad (OpenJSCAD.org Source)

/storage/safe/ogi-it/Projekte/IOT_Gadgets/oios/packages/rs232w_case/node_modules/openscad-openjscad-translator/src/parserCJS.js:530
        throw new _parseError(str, hash);
        ^
Error: Parse error on line 1007:

----------------------^
Expecting '(', got '='

I'm using the latest dev version commit c700910
Any Ideas on this? Thanks Ognian

kaosat-dev commented 7 years ago

Hi @Ognian ! Sadly this is because it uses the 'newer' parts of the Openscad syntax which are not supported by Openjscad at this time (ie things like function etc) Btw for all things related to the openscad to jscad conversion please post the issue here : https://github.com/jscad/openscad-openjscad-translator/issues , thanks ! :)

Ognian commented 7 years ago

@kaosat-dev ok, I understand. I'll try to find another "workflow". With another scad part converting to jscad I found out that parameters are not preserved in the conversion, so that you get jscad parameters. Therefore using scad part libraries in jscad is not that easy... Thanks Ognian

kaosat-dev commented 7 years ago

@Ognian what parameters are not preserved ? Do you have an example ? Yes, reusing directly openscad libs in Jscad might not be possible but a partial auto/manual conversion might be : btw currently the output of the conversion is 'hidden' (it seems like you are still in openscad mode) which I think is bad, we should do openscad => jscad (+ manual edit)

Ognian commented 7 years ago

@kaosat-dev I'm trying to build a case for an ESP8266 project I'm developing. So I found the most important things already done by others

  1. the box jscad-utils/jscad-boxes.jscad (jscad, already working)
  2. the ESP8266 lib http://www.thingiverse.com/thing:1933779/#files (scad, no way to automatically convert since it uses modules etc.)
  3. snapfit.scad (http://www.thingiverse.com/thing:1799553)

Lets start with the easiest one snapfit.scad

//snap fit connectors

// column width
w=20;
// main column height
h=10;
// snap fit width
s=2;
//snap fit height
f=2;
// mini column height
m=5;
// tolerance
t=0.5;

$fn=100;

module arrow(){
difference(){
union(){
translate([0,0,h/2+m])cylinder (r1=s, r2=1, h=f, center=true); //arrow head
translate([0,0,h/2+m/2])cylinder(r=s-t, h=m, center=true); //mini column
        }
translate([0,0,h/2+m])cube([s/3,s*2,f+m], center=true); //cut in snap fit
                }
                    }
difference(){
union(){
cylinder (r=w/2, h=h, center=true); //main cylinder
arrow();
        }
union(){
translate([0,0,-h/2+m])cylinder (r1=s+t, r2=1+t, h=f+t, center=true); //arrow head
translate([0,0,-h/2+m/2])cylinder(r=s-t/2, h=m+t, center=true); //mini column
        }
}

when converting to jscad I get:

// source: snapfit.jscad

// producer: OpenJSCAD 0.5.2
function main() {

    return CSG.cylinder({
        start: [0, 0, -5],
        end: [0, 0, 5],
        radiusStart: 10,
        radiusEnd: 10,
        resolution: 100
    }).union([CSG.cylinder({
        start: [0, 0, -1],
        end: [0, 0, 1],
        radiusStart: 2,
        radiusEnd: 1,
        resolution: 100
    }).translate([0, 0, 10]).union([CSG.cylinder({
        start: [0, 0, -2.5],
        end: [0, 0, 2.5],
        radiusStart: 1.5,
        radiusEnd: 1.5,
        resolution: 100
    }).translate([0, 0, 7.5])]).subtract([CSG.cube({
        center: [0, 0, 0],
        radius: [0.3333333333333333, 2, 3.5],
        resolution: 16
    }).translate([0, 0, 10])])]).subtract([CSG.cylinder({
        start: [0, 0, -1.25],
        end: [0, 0, 1.25],
        radiusStart: 2.5,
        radiusEnd: 1.5,
        resolution: 100
    }).translate([0, 0, 0]).union([CSG.cylinder({
        start: [0, 0, -2.75],
        end: [0, 0, 2.75],
        radiusStart: 1.75,
        radiusEnd: 1.75,
        resolution: 100
    }).translate([0, 0, -2.5])])]);
};
var wrappedMain = main
main = function () {
    var paramsDefinition = (typeof getParameterDefinitions !== 'undefined') ? getParameterDefinitions : undefined
    return wrappedMain(getParameterDefinitionsCLI(paramsDefinition, {}))
}

all parameters (variables) like w, h etc. are gone; they get replaced by the actual values... of course this is a very basic example; rewriting it for jscad wouldn't be that complicated BUT that's not the point, if i work with jscad I would like to be able to use the huge scad code base in the internet without much efforts...

What comes to my mind to solve this issue, are the so called ES6 template strings:

let a=2
let b=3
console log(`the result is ${a+b}`)

see https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/template_strings

so we could have a function in jscad having as a parameter a simple string of scad commands. so that the above scad code could be "included" in jscad like:

const columnWidth=22; //just one param for this example
fromScad(`
//snap fit connectors

// column width
w={columnWidth};
// main column height
h=10;
// snap fit width
s=2;
//snap fit height
f=2;
// mini column height
m=5;
// tolerance
t=0.5;

$fn=100;

module arrow(){
difference(){
union(){
translate([0,0,h/2+m])cylinder (r1=s, r2=1, h=f, center=true); //arrow head
translate([0,0,h/2+m/2])cylinder(r=s-t, h=m, center=true); //mini column
        }
translate([0,0,h/2+m])cube([s/3,s*2,f+m], center=true); //cut in snap fit
                }
                    }
difference(){
union(){
cylinder (r=w/2, h=h, center=true); //main cylinder
arrow();
        }
union(){
translate([0,0,-h/2+m])cylinder (r1=s+t, r2=1+t, h=f+t, center=true); //arrow head
translate([0,0,-h/2+m/2])cylinder(r=s-t/2, h=m+t, center=true); //mini column
        }
}
`);

notice the fromScad function and the ES6 template instead the string parameter of this function, maybe there is something like this already in jscad.

The next step would be to include the ESP8266 board:

const position x =[15, 0, 0];
fromScad(`
use <ESP8266Models.scad>
translate(${x}) {
    // nodeMCU module
    NodeMCU(pins=0, phmc="Yellow", phfc="DarkGrey");

    // USB connector locator function
    // Can be used to cut a hole for the USB connector
    translate([0, -6/2,0])
        NodeMCU_USBLocate() #cube([6.87+1.4, 6, 1.85+1.4], center=true);

    // Push Buttons locator function
    // Can be used to cut a hole for access
    NodeMCU_PBLocate()
        {
            translate([0, 10/2, 0])
                #cube([2, 10, 1], center=true);
            translate([0, 10/2, 0])
                %cube([2, 10, 1], center=true);
        }
}
`

This was now a little bit lengthy, but I hope you can get the idea behind it. If we want jscad to be an alternative for scad this way must be gone somehow.

For my current project I'm not sure if using only scad isn't the easier solution for now... Ognian

kaosat-dev commented 7 years ago

@Ognian that is a really bad bug in the translation ! Could you please open an issue (just copy and paste this) here ? https://github.com/jscad/scad-api While your proposal to use template literals would be a possible one , the fact is, the translator should not behave the way it does in the first place :)