lambdaway
::
pforms5
8
|
list
|
login
|
load
|
|
_h1 pforms ( [[1|?view=pforms]] | [[2|?view=pforms2]] | [[3|?view=pforms3]] | [[4|?view=pforms4]] | 5 | [[6|?view=pforms6]] ) {div {@ style="position:relative;"} {div {@ id="W3D"} {W3D -40 0 75 1.0 500}} {pre {@ style="position:absolute; top:0px; left:10px; "} {W3D.parameter R/ox rox 320 0 360 5} {W3D.parameter R/oy roy 0 0 360 5} {W3D.parameter R/oz roz 40 0 360 5} {W3D.parameter scal scale 1.0 0.1 2.0 0.1} }} _h2 world {pre '{def W3D {lambda {:ox :oy :oz :scal :pers} {{W3D.open 580 580} {{W3D.frame 580 580} {W3D.init :ox :oy :oz :scal :pers} {W3D.addForm 3 #000 [0,0,0,1] {W3D.point 0 0 0 1 30}} {W3D.addForm 2 #f00 [0,0,0,1] [[-150,0,0,1],[150,0,0,1]]} {W3D.addForm 2 #0f0 [0,0,0,1] [[0,-150,0,1],[0,150,0,1]]} {W3D.addForm 2 #00f [0,0,0,1] [[0,0,-150,1],[0,0,150,1]]} {W3D.addForm 2 #888 [0,0,0,1] {W3D.cube 150}} {S.map {lambda {:a} {W3D.addForm 1 #444 [:a,0,0,1] {myPolyline}} } {S.serie 0 -180 -2}} {W3D.addForm 5 #f00 [0,0,0,1] {W3D.blossom 5 {W3D.stretch 0.2 0.8 [{p0},{p1},{p2},{p3}] }}} {S.map {lambda {:i} {W3D.addForm 1 rgb(:i,0,{- 250 :i}) [0,0,:i,1] {W3D.blossom 4 [{p0},{p1},{p2},{p3}] }}} {S.serie 0 270 10}} }}}} -> {def W3D {lambda {:ox :oy :oz :scal :pers} {{W3D.open 580 580} {{W3D.frame 580 580} {W3D.init :ox :oy :oz :scal :pers} {W3D.addForm 3 #000 [0,0,0,1] {W3D.point 0 0 0 1 30}} {W3D.addForm 2 #f00 [0,0,0,1] [[-150,0,0,1],[150,0,0,1]]} {W3D.addForm 2 #0f0 [0,0,0,1] [[0,-150,0,1],[0,150,0,1]]} {W3D.addForm 2 #00f [0,0,0,1] [[0,0,-150,1],[0,0,150,1]]} {W3D.addForm 2 #888 [0,0,0,1] {W3D.cube 150}} {S.map {lambda {:a} {W3D.addForm 1 #444 [:a,0,0,1] {myPolyline}} } {S.serie 0 -180 -2}} {W3D.addForm 5 #f00 [0,0,0,1] {W3D.blossom 5 {W3D.stretch 0.2 0.8 [{p0},{p1},{p2},{p3}] }}} {S.map {lambda {:i} {W3D.addForm 1 rgb(:i,0,{- 250 :i}) [0,0,:i,1] {W3D.blossom 4 [{p0},{p1},{p2},{p3}] }}} {S.serie 0 270 10}} }}}} {def W3D.open {lambda {:w :h} svg {@ width=":w" height=":h" style="box-shadow:0 0 0px #000; background:#eee; border:0px solid #000;"}}} {def W3D.frame {lambda {:w :h} g {@ id="forms" transform="translate({/ :w 2},{/ :h 2})"}}} {def W3D.parameter {lambda {:name :id :val :min :max :step} :name : {input {@ id=":id" type="text" value=":val" size="5" style="background:#fff; color:#000; border:0px solid"}} {input {@ type="range" min=":min" max=":max" value=":val" step=":step" style="width:110px; vertical-align:middle;" oninput="W3D.camera(':id', this.value)"}}}} {def W3D.addForm {lambda {:w :col :m :points} {path {@ d="{W3D.polyline :m :points}" fill="transparent" stroke-width=":w" stroke=":col"}}}} } _h2 forms {pre {def W3D.point {lambda {:x :y :z :w :s} [[{- :x :s},:y,:z,:w],[{+ :x :s},:y,:z,:w],[:x,:y,:z,:w], [:x,{- :y :s},:z,:w],[:x,{+ :y :s},:z,:w],[:x,:y,:z,:w], [:x,:y,{- :z :s},:w],[:x,:y,{+ :z :s},:w]] }} {def W3D.cube {lambda {:d} [[-:d,-:d,-:d,1], [:d,-:d,-:d,1], [:d,:d,-:d,1], [-:d,:d,-:d,1], [-:d,:d,:d,1], [:d,:d,:d,1], [:d,-:d,:d,1], [-:d,-:d,:d,1], [-:d,-:d,-:d,1]] }} {def W3D.polygon {def W3D.polygon.r {lambda {:r :k :i} {if {< :i 0} then [{* :r {cos {* :k :i}}},{* :r {sin {* :k :i}}},0,1] else [{* :r {cos {* :k :i}}},{* :r {sin {* :k :i}}},0,1], {W3D.polygon.r :r :k {- :i 1}} }}} {lambda {:r :n} [{W3D.polygon.r :r {/ {* 2 {PI}} :n} :n}] }} '{def myPolyline [ [0,50,0,1], [50,50,0,1], [50,50,50,1], [0,50,50,1], [0,50,150,1] ] } -> {def myPolyline [[0,50,0,1], [50,50,0,1], [50,50,50,1], [0,50,50,1], [0,50,150,1] ] } '{S.map {lambda {:a} {W3D.addForm 1 // line width #444 // line color [:a,0,0,1] // transformation {myPolyline}}} // the polyline {S.serie 0 -180 -2} // from 0 to -180 with steps -2 } } _h2 pForms ;; _p More explanations in [[decasteljau]]. {pre 1) defining 4 control 4Dpoints '{def p0 [-150,-150,-150,1]} -> {def p0 [-150,-150,-150,1]} '{def p1 [ 150,-150,-150,1]} -> {def p1 [ 150,-150,-150,1]} '{def p2 [ 150,-150, 150,1]} -> {def p2 [ 150,-150, 150,1]} '{def p3 [ 150, 150, 150,1]} -> {def p3 [ 150, 150, 150,1]} 2) adding the cubic curve '{addForm 5 // line width #f00 or rgb(255,0,0) // line color is red [0,0,0,1] // no transformation {W3D.blossom // the curve 5 // level of recursion {W3D.stretch // control polygon stretched 0.2 // from t = 0.2 0.8 // to t = 0.2 [{p0},{p1},{p2},{p3}] // control polygon }}} 3) adding 28 rational bézier cubic curves rotating around Oz '{S.map {lambda {:i} // repeat ... {W3D.addForm // add curve 1 // line width rgb(:i,0,{- 250 :i}) // variable color [0,0,:i,0] // transform {W3D.blossom 4 // level of recursion [{p0},{p1},{p2},{p3}] }}} {S.serie 0 270 10}} // ... from 0 to 270 step 10 } {script var W3D = (function() { var CAM = []; // W3D global : 3D camera function init( rox,roy,roz,scal,pers ) { CAM = [ [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] ]; CAM = product( CAM, perspective( pers ) ); CAM = product( CAM, rotate( 'OX', rox ) ); CAM = product( CAM, rotate( 'OY', roy ) ); CAM = product( CAM, rotate( 'OZ', roz ) ); CAM = product( CAM, scale( scal, -scal, -scal ) ); } var camera = function(id,val) { var rox = (id === 'rox')? val : document.getElementById("rox").value; var roy = (id === 'roy')? val : document.getElementById("roy").value; var roz = (id === 'roz')? val : document.getElementById("roz").value; var sca = (id === 'scale')? val : document.getElementById("scale").value; document.getElementById(id).value = val; var newWorld = "{W3D " + rox + " " + roy + " " + roz + " " + sca + " " + " 500}"; document.getElementById('W3D').innerHTML = LAMBDATALK.eval_forms( newWorld ) }; function rotate( axe, a ) { // R4 -> R4 var a = 2*Math.PI/360*a, cosa = Math.cos(a), sina = Math.sin(a); return (axe === 'OX') ? [ [1,0,0,0], [0,cosa,-sina,0], [0,sina,cosa,0], [0,0,0,1] ] : (axe === 'OY') ? [ [cosa,0,sina,0], [0,1,0,0], [-sina,0,cosa,0], [0,0,0,1] ] : (axe === 'OZ') ? [ [cosa,-sina,0,0], [sina,cosa,0,0], [0,0,1,0], [0,0,0,1] ] : '' } function scale( sx, sy, sz ) { // R4 -> R4 return [ [sx,0,0,0], [0,sy,0,0], [0,0,sz,0], [0,0,0,1] ]; } function translate( tx, ty, tz ) { // R4 -> R4 return [ [1,0,0,tx], [0,1,0,ty], [0,0,1,tz], [0,0,0,1] ]; } function perspective ( f ) { // R4 -> R4 ( x=X, y=Y, z=Z, w=Z/f+1 ) return [ [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,1/f,1] ]; } function product ( m1, m2 ) { // 4x4 matrix * 4x4 matrix -> 4x4 matrix var m = []; for (var i=0; i< 4; i++) { var mm = []; for (var j=0; j< 4; j++) { var s = 0; for (var k=0; k< 4; k++) { s += m1[i][k]*m2[k][j]; } mm[j] = s; } m[i] = mm; } return m; } function transform ( m, p0 ) { // apply m on a 4D point var p1 = []; for (var i=0; i< 4; i++) { var temp = 0; for (var j=0; j< 4; j++) temp += m[i][j]*p0[j]; p1[i] = temp; } return p1 // return a R4 point } function polyline ( t , f ) { var NEAR = -400, FAR = 500; var m = product( product( product( product( CAM, rotate( 'OX', t[0] ) ), rotate( 'OY', t[1] ) ), rotate( 'OZ', t[2] ) ), scale( t[3], t[3], t[3] ) ) var tab = []; for (var i=0; i< f.length; i++) { var p = transform( m, f[i] ); tab[i] = [p[0]/p[3], p[1]/p[3], p[2]/p[3]]; } // draw only segments entirely in clipping planes var poly = ''; for (var i=0; i< tab.length-1; i++) { if ( tab[i][2] > NEAR && tab[i][2] < FAR && tab[i+1][2] > NEAR && tab[i+1][2] < FAR ) poly += 'M ' + tab[i][0] + ',' + tab[i][1] + ' ' + tab[i+1][0] + ',' + tab[i+1][1] + ' '; } return poly // a SVG formated polyline } // de casteljau var interpol = function(a,b,t) { return [ a[0]*(1-t)+b[0]*t, a[1]*(1-t)+b[1]*t, a[2]*(1-t)+b[2]*t, a[3]*(1-t)+b[3]*t ] }; var sub = function(arr,acc,t) { if (arr.length < 2) return acc; else { acc.push( interpol(arr[0],arr[1],t) ); return sub( arr.slice(1,),acc,t ) } }; var split = function(arr,acc,t,lr) { if (arr.length < 1) return acc else { if (lr) acc.push( arr[0] ) else acc.unshift( arr[arr.length-1] ) return split( sub(arr,[],t), acc, t, lr ) } }; var stretch = function(arr,t0,t1) { return split( split(arr,[],t0,false), [], t1, true) }; var blossom = function(arr,n) { if (n < 1) return arr else return [blossom( split(arr,[],0.5,true), n-1 ), blossom( split(arr,[],0.5,false), n-1 )] }; // PUBLIC FUNCTIONS return { init:init, camera:camera, polyline:polyline, stretch:stretch, blossom:blossom }; })(); // end W3D LAMBDATALK.DICT['W3D.init'] = function() { // {W3D.init3D ox oy oz sc pers} var args = LAMBDATALK.supertrim(arguments[0]).split(" "); return W3D.init( args[0], args[1], args[2], args[3], args[4] ) }; LAMBDATALK.DICT['W3D.polyline'] = function() { // {W3D.polyline [[...]] p} var args = LAMBDATALK.supertrim(arguments[0]).split(" "); var m = JSON.parse(args.shift()); var p = JSON.parse( args.join(" ")); return W3D.polyline(m,p) }; LAMBDATALK.DICT['W3D.stretch'] = function() { // {stretch t0 t1 [[...]]} var args = LAMBDATALK.supertrim(arguments[0]).split(" "); var t0 = parseFloat( args.shift()); var t1 = parseFloat( args.shift()); var arr = JSON.parse(args.join(" ")); return JSON.stringify(W3D.stretch(arr,t0,t1)) }; LAMBDATALK.DICT['W3D.blossom'] = function() { // {blossom n [[...]]} var args = LAMBDATALK.supertrim(arguments[0]).split(" "); var n = parseFloat(args.shift()); return "["+JSON.stringify(W3D.blossom( JSON.parse(args.join(" ")), n )) .replace( /\[{2,}/g, "[" ) .replace( /\]{2,}/g, "]" )+"]" }; }
lambdaway v.20211111