跳到内容

enkimute/ganja.js

ganja.js-javascript的几何代数。

G公司几何测量的A类代数-N个其他J型美国科技大学A类代数

Ganja.js是一个用于javascript的几何代数代码生成器。它生成Clifford代数和任何签名和实现算子的子代数重载和代数常数。

引用为内政部

@杂项{甘贾.js,国防部={10.5281/ZENODO公司.3635774},网址={https://zenodo.org/record/3635774},作者={史蒂文·德凯宁克},标题={甘贾.js},如何发布={泽诺。https://doi.org/10.5281/ZENODO.3635774},={2020}}

(数学上,由ganja.js生成的代数是分级外部(Grassmann)代数(或其子代数之一)具有非度量外积,扩展(Clifford)具有几何内积和收缩内积,Poincare对偶算子和主对合和形态。)

(从技术上讲,ganja.js是一个代码生成器,它生成将代数文字具体化的类和表达式,使用反射、内置标记器和简单的AST转换器将包含代数结构的函数重写为过程对应的函数。)

(实际上,ganja.js使用元素、向量和矩阵在javascript中启用真正的数学语法操作超过雷亚尔,复数,双重数字,双曲线数,向量,时空事件,四元数,对偶四元数,四元法任何其他Clifford代数.)

(严肃地,看看示例,使用G计算器或者玩楔形游戏第一个。)

话语与不和谐

访问二元网为我们的论坛和聊天-完美提问和支持的地方。

新增!

js现在有一个基于nodejs的模板化源代码生成器,可以创建任意代数对于C++,C类#,蟒蛇。生成的代码提供了平面多向量格式和运算符重载。检查源代码的“codegen”文件夹,预生成版本中有几个代数可用。

目录

1.使用甘菊的原因
2.首次使用甘菊
3.免费获取甘菊样品
4.为有经验的用户提供Ganja
5.甘菊成分和语法
6.Ganja starterkit:PGA2D P(R*2,0,1)
7.Ganja starterkit:PGA3D P(R*3,0,1)

使用甘菊的原因

Ganja.js使在浏览器中进行几何代数变得简单有趣。内联语法和图形使浏览器中的数学看起来像。。数学。

  • 操作员过载
  • 代数常数
  • 支持任何度量(正、负、零)和维度(也支持+10)
  • 小(线上20kb)
  • 无矩阵逆运算可达5D。
  • 几何、内部(左收缩)、外部(楔形)和回归(V形)乘积
  • 共轭,反向,渐开线,对偶(彭加莱),负
  • 4个API(内联、asciimath、面向对象、功能性)
  • 用于1D和2D功能、投影2D、3D和共形2D和3D元素的简单图形功能。(SVG/webGL/OPNS)
  • 支持其所有代数中的向量和矩阵。
  • 有一个游戏这会教你如何使用ganja.js!

首次使用ganja

使用npm安装ganja.js:

npm安装ganja.js

并在脚本中要求:

无功功率,无功功率 代数=要求('ganja.js');

或者在浏览器中,只需包含ganja.js脚本。(ganja.js没有依赖项)

净现值法

<脚本 SRC公司="https://unpkg.com/ganja.js"></脚本>

代数函数

要创建代数,请调用代数指定度量的函数签名(正维度、负维度和零维度的数量)。结果是实现所请求的clifford代数的ES6类。

功能 代数( 第页, q个, 第页, 函数 );
  //p=正尺寸数。
  //q=可选的负尺寸数。
  //r=可选的零维数。
  //func=可选函数。(速记..它被传递到.inline并执行)

还提供了一个扩展语法,允许您进一步调整创建的代数。

功能 代数( 选项, 函数 );
  //options=包含子集的对象
  //           {
  //p,正维数的整数。
  //q,负维的整数。
  //r,零维的整数。
  //metric,[a,b,..]数组,每个生成维度具有metric。(例如,PGA2D为[0,1,1])
  //基础,[“1”,“e1”,”e2“]基础,推翻了标准的cannonical基础。
  //Cayley,[[“1”,“e1”],[“e1”,“-1”]]Cayley表否决标准GA表。
  //baseType、float32Array(默认)、float64Array、。。用于元素的baseType。
  //mix设置为true以启用可互操作的子代数。(默认为false)。
  //           }


  //返回:如果没有提供函数,则返回代数类;如果提供了函数,则为函数结果。

以下是一些示例:

//基本
无功功率,无功功率 超(Hyper)   = 代数(1);       //双曲型数字。
无功功率,无功功率 复杂 = 代数(0,1);     //复数。
无功功率,无功功率 二重的    = 代数(0,0,1);   //双重数字。
无功功率,无功功率 H(H)       = 代数(0,2);     //四元数。

//克利福德
变量 二氧化氯 = 代数(2);           //二维向量空间的Clifford代数。
无功功率,无功功率 氯离子 = 代数();           //三维向量空间的Clifford代数。
无功功率,无功功率 timeSpace(时间空间) = 代数(1,);   //时空向量的Clifford代数。

//子代数
无功功率,无功功率 复杂 = 代数({第页:,基础:['1',“e123”]});        //作为Cl3子代数的复数
无功功率,无功功率 H(H) = 代数({第页:,基础:['1',“e12”,“e13”,“e23”]});   //四元数作为Cl3的偶子代数

//几何
无功功率,无功功率 第2d页 = 代数(2,0,1);     //投影欧几里德二维平面。(双重)
无功功率,无功功率 PGA3D系列 = 代数(,0,1);     //投影欧几里德三维空间。(双重)
无功功率,无功功率 CGA2D公司 = 代数(,1);       //保形2D空间。
无功功率,无功功率 CGA3D公司 = 代数(4,1);       //保形3D空间。

//高维GA
无功功率,无功功率 DCGA3D公司 = 代数(6,2);      //双共形3D空间。
无功功率,无功功率 tcga3天 = 代数(9,);      //三重共形3D空间。
无功功率,无功功率 DCGSTA公司 = 代数(4,8);      //双共形几何时空代数。
无功功率,无功功率 QCGA公司   = 代数(9,6);      //二次共形几何代数。

现在可以使用这些类生成代数元素。这些元素将具有所有预期属性。(长度、刀片访问、点、楔、多、双、反向等…)

虽然没有建议,但您可以像下面的示例那样在“经典”编程风格语法中使用它们。

无功功率,无功功率 复杂 = 代数(0,1);     //复数。
无功功率,无功功率  = 新的 复杂([,2]);     //3+2i
无功功率,无功功率 b = 新的 综合体([1,4]);     //1+4i
返回 .穆尔(b);                //返回[-5,14]

然而,这并不是很漂亮。这也没那么有趣。幸运的是,js提供了另一种编写代数函数、文字的方法和表达式。

内联函数

您的代数类通过内联功能。它接受一个javascript函数,并将其转换为使用你选择的代数。使用内联函数,上述示例为写入:

代数(0,1).内联(()=>(+第2版)*(1+第四版))();  //返回[-5,14]

注意,如果您立即执行该函数,可以将其添加为最后一个参数到您的代数构造函数调用。

代数(0,1,()=>(+第2版)*(1+第四版)); //返回[-5,14]

内联语法功能强大且灵活。它提供完整的操作员重载,重载科学电子符号,允许您直接指定基本叶片并允许使用数组或lambda表达式在代数表达式中调用括号的必要性。

代数(2,0,1,()=>{

  //使用电子符号直接规范基础叶片。
  无功功率,无功功率 xy_支路 = 第1页,
      伪标量 = 2012年1月;

  //运算符重载..*=几何积,^=楔形,&=V形,<<=点,>>=三明治。。。
  无功功率,无功功率 来自产品的xy支路 = 第1页 * 1个2;

  //直接指定点。
  无功功率,无功功率 某个点 = 第1页 + 0.4电子01 + 0.5电子02;  

  //返回点的函数。
  无功功率,无功功率 函数_ hat_returns_point = ()=>某个点 + 0.5电子01;

  //点与函数的连接。。请注意,没有调用方括号。。
  无功功率,无功功率 点与函数之间的连接 = 某个点 & 函数_目标_返回点;

  //同上。。但作为功能。。(如果点更改,也会更新)
  无功功率,无功功率 函数_that_returns_join = ()=>某个点 & 函数_目标_返回点;

  //数组上的二进制操作也按预期工作。
  无功功率,无功功率 即使 = [1,2,,4,5]*2;

  //即使它们包含多向量或其他数组:
  无功功率,无功功率 时髦的 = [1, 第1页01+0.5电子02, [,4]] *  + [1,2,];

  //所有元素和函数都可以直接呈现。(同样,没有调用方括号)。
  无功功率,无功功率 帆布 = .图表([ 某个点, 函数_目标_返回点, 函数_that_returns_join ]);

});

在后台,ganja.js将翻译这些函数。

//漂亮的数学表达式(!=对偶,^=楔形)

 = ()=>!(!^!b)*(c(c)*1电子23)

//转换为。。

b = ()=>.穆尔(.二重的((.楔子(.二重的(),.二重的(b)))),(.穆尔(c(c),.科夫(6,1))))

在上面的示例中,函数b做同样的事,但应该清楚的是a-b=头痛.因为我的阿司匹林用完了,我会把证据留给读者。

请参阅咖啡店了解更多信息如何使用内联语法的示例。

图形函数。

你的代数也暴露了一个静态图表允许您执行以下操作的函数轻松绘制1D或2D函数以及2D和3D PGA和CGA元素。

  • 画布输出可用于1D和2D功能。
  • SVG输出可用于2D PGA、3D PGA和2D CGA。
  • webGL输出可用于3D PGA和3D CGA。
  • webGL2隐式OPNS渲染可用于所有其他空间。
帆布 = 代数(0).图表(x个=>数学.(x个*5));                   //在R中绘制1D函数

帆布 = 代数(0).图表((x个,)=>x个+);                         //绘制R中的2D函数

高级副总裁 = 代数(2,0,1,()=>.图表([第1页,第1页,1个2]));           //在2D PGA中绘制原点以及x和y轴

高级副总裁 = 代数(,0,1,()=>.图表([第123页,1电子23,1电子13,第1页],{照相机:1+.5e01型-.5e02版})); //和3D PGA

帆布 = 代数(4,1,()=>.图表([.5电子4-.5电子5],{保角的:真的,全球:真的}); //3D CGA的起源

同样,更多示例可以在咖啡馆.

描述函数。

要显示基本叶片名称、公制、Cayley表等,请使用静止的描述功能。

代数(0,1).描述();

样本输出:

依据1,e1公制-1凯利1,e1e1,-1矩阵形式:A、 -B类B、 A类

获得免费的甘菊样品。

请访问咖啡馆并与这些示例进行互动。它们是交互式的,您可以轻松地在线更改代码。无需下载或安装任何东西!

复曼德布罗特
复数最小二乘法
双重微分
双向反向传播
四元数色调
四元数mandelbrot
时空洛伦兹
pga2d点和线
pga2d距离和角度
pga2d项目和拒绝
pga2d转子和转换器
pga2d等距图
pga2d逆运动学
pga2d分离轴
pga2d姿态估计
pga2d欧拉线
pga2d-desargues定理
pga2d分化
pga2d物理月球
pga2d折纸
pga2d水芹
pga3d点和线
pga3d距离和角度
pga3d转子和转换器
pga3d二十面体
pga3d采样
pga3d切片
pga3d分化
pga3d蒙皮
pga3d物理行星
pga3d折纸
pga3d物理对称顶
pga3d物理免费上衣
pga3d对象
cga2d点和圆
cga2d项目和拒绝
cga2d转子和转换器
cga2d欧拉线
cga3d点-圆-线
cga3d点球体平面
cga3d双球面
cga3d交叉口
cga3d项目拒绝
cga3d opns可视化工具
cga3d opns线圆
cga3d json
mga3d点和线
ccga3d点二次曲面
qcga3d点及更多
游戏楔形物

js也是GAcalculator背后的引擎-试试看联机或者把它放在游戏商店

或者-通过玩楔形游戏.

Ganja适合有经验的用户。

js允许您进一步自定义代数类生成,允许您生成子代数(谁的元素使用更少的存储空间),或者代数是您决定顺序和名称的地方基础叶片。(名称应始终为exyz公司但是你可以选择例如e20而不是默认的e02并期望ganja.js进行适当的符号更改)

高级选项可以通过将选项对象作为的第一个参数代数呼叫。

自定义子代数

//作为R2偶子代数的复数
C类 = 代数({第页:2,基础:['1',“e12”]});

//作为R3偶子代数的四元数
无功功率,无功功率 H(H) = 代数({第页:,基础:['1',“e12”,“e13”,“e23”]});  

自定义基础名称。

如果未指定,ganja.js将生成以下基名称按等级分组并按数字排序。默认情况下,单个零维度将获得生成器名称e0零维到来第一。

签名 默认基础名称
2,0,0和1,1,0 1,e1,e2,电子12
1,0,1 1,e0,电子1,电子01
3,0,0和2,1,0 1,e1,电子2,电子,e12,电子13,电子23,电子123
2,0,1 1,e0,电子1,电子2,电子01,e02,电子12,电子012
4,0,0和3,1,0 1,e1,电子2,电子,电子4,电子12,电子13,电子14,电子23,电子24,电子34,电子123,电子124,电子134,电子234,电子1234
3,0,1 1,e0,电子1,电子2,电子,电子01,电子02,电子03,电子12,电子13,e23,电子012,电子013,电子023,电子123,电子0123

笔记多向量的标量部分“mv”可以用“mv.s”,其他基础叶片遵循预期模式。例如。“mv.e12”“mv.e012”.

默认情况下,代数元素将继承自Float32Array。您可以将ganja.js使用的底层数据类型更改为类型化数组基类型:

无功功率,无功功率 R3_32段 = 代数();

无功功率,无功功率 64兰特 = 代数({第页:,基本类型:Float64数组});

自定义Cayley表

或者更进一步,简单地指定一个您喜欢的Cayley表。下面的示例显示自动数值微分并计算任何多项式的值、一阶、二阶和三阶导数。

无功功率,无功功率 基础=['1',“e1”,“e2”,“e3”];
无功功率,无功功率 凯利=[['1', “e1”,“e2”,“e3”],
            [“e1”,“e2”,“e3”, '0'],
            [“e2”,“e3”, '0', '0'],
            [“e3”, '0', '0', '0']];

代数({基础,凯利},()=>{
  无功功率,无功功率 (f) = (x个)=>0.25*x个*x个*x个*x个-0.5; 
  对于 (无功功率,无功功率 =-5; <5; ++) 慰问.日志( , (f)(+第1页) );
});

输出:x[f(x),f'(x)、f''(x)/2!,f''(x)/3!]

-5 [155.75, -125, 37.5, -5]-4[63.5,-64,24,-4]-3 [ 19.75,  -27, 13.5, -3]-2 [   3.5,   -8,    6, -2]-1 [ -0.25,   -1,  1.5, -1]0  [  -0.5,    0,    0,  0]1  [ -0.25,    1,  1.5,  1]2  [   3.5,    8,    6,  2]3  [ 19.75,   27, 13.5,  3]4  [  63.5,   64,   24,  4]

混合模式。

出于存储和性能方面的原因,组合以下各种子代数的元素可能很有趣给定的代数。Ganja.js通过在创建代数时将options.mix设置为true来支持这一点。

//创建R2-克利福德2D向量代数-表示您想要混合模式。
无功功率,无功功率 R2级 = 代数({第页:2,q个:0,第页:0,混合:真的}); 

//创建复数作为R2的偶子代数。
无功功率,无功功率 C类  = 代数({第页:2,q个:0,第页:0,基础:['1',“e12”],混合:真的});

//R2的元素有四个成分。
//创建复数1+4i
无功功率,无功功率 =新的 R2级([1,0,0,4])

//C元素有两个组件。
//创建复数3+2i
无功功率,无功功率 b=新的 C类([,2]); 

//他们互相操作。。
.穆尔(b);   //返回R2元素:[-5,0,0,14]
b.Mul公司();   //返回C:[-5,14]的元素

使用混合模式启用后,ganja.js生成的所有操作都将使用基本名称访问而不是数组索引。(所有操作都受到保护,以将缺失的叶片替换为0)。

内联语法仍然可以使用,请记住,在大多数情况下,您希望这样父代数的内联函数。(在上例中,使用R2.Inline而不是C.Inline因为后者会将您的所有操作减少到C)字段。

甘菊成分和语法。

以下是所有语法风格支持的运算符列表:

请注意,操作符优先级在javaScript中始终是一样的,除了对于优先于*和/的楔形、V形、圆点和三明治,导致许多常见GA表达式中的括号更少。

优先顺序 内联JS AsciiMath数学 面向对象 功能
5 x.渐开线 波浪线(x) x.渐开线 A.渐开线(x)
5 x.反向 滴滴涕(x) x.反向 A.反向(x)
5 ~x个 帽子(x) x.共轭 A.共轭(x)
5 !x个 钢筋(x) x.双重 A.双(x)
4升 x**-1个 x ^-1 x.反向 A.逆(x)
4升 x年 x ^y年 x.Pow(y) A.Pow(x,y)
x ^y年 x ^^y年 x.楔(y) A.楔子(x,y)
x<<y x*年 x.点(y) A.点(x,y)
x轴(&y) 巴(巴(x)^^巴(y)) x.V(y) A.V(x,y)
x> >>年 x**y**帽子(x) x.Mul(y)。Mul(x.共轭) A.sw(x,y)
2 x年 x年*月 x.倍数(y) A.Mul(x,y)
2 x年 x年 x.Div(y) A.Div(x,y)
1 x-y坐标 x-y坐标 x.子(y) A.子项(x,y)
1 x+y x+y x.添加(y) A.加(x,y)
第1页 1e_1 新A([0,1]) A.矢量(1)
第2页 2e_2号机组 新A([0,0,2,0]) A.矢量(0,2)
第2页第12页 第2页,共12页 新A([0,0,0,2]) A.双矢量(2)

二元性

对偶算子实现了庞加莱对偶,这是一个有效的定义和实现即使所考虑的子空间的伪标量是退化的。它是为任何k向量x个作为n-k向量的n维子空间包含所有基础不在中的向量x个。对于非退化度量,您仍然可以使用乘法如果需要,可以使用伪标量(尽管效率会降低)

点积

实现的点积是左收缩,没有任何扩展或修改。几何意义通常表示为x个给出了正交补语in的投影x个到上面.

V形产品

V形产品是一种优化的缩写,用于表示楔形对偶的对偶。

a&b=!(!a^!b)

我选择了&符号,因为它可以根据几何图形解释为“连接”或“相遇”赋予向量的含义。(平面/直线或点)

Ganja starterkit:PGA2D P(R*2,0,1)

想快速开始学习2D射影几何代数吗?这个下面的锅炉板让你带着一堆有用的身份。(咖啡馆有很多例子)。

我们从带有签名(2,0,1)的clifford代数开始。然后我们通过几何扩展将其升级为几何代数操作员。(这就是我们决定我们的二元体将是点的地方,有效地使该P(R*2,0,1).

只需包含ganja.js脚本并将下面的块放在脚本标签开始。。

//用2个正生成器和1个零生成器创建一个Clifford代数。
代数(2,0,1,()=>{
    
    //将代数信息输出到控制台。
    .描述();
    
    //默认基础为s、e0、e1、e2、e01、e02、e12、e012
    //向量的度量为0、1、1-向量将表示直线。
    //双向量的度量是0,0,-1-双向量将表示点。
    //伪标量是退化的,所以请使用内置的对偶运算符。
    
    //双矢量由两个电机元件和一个旋转元件组成-
    //准确地表示平面中的平移和旋转所需的内容。
    
    //在对偶投影空间中,原点由e12双向量表示。
    无功功率,无功功率 起源 = 第1页, 前任=-第1页02, 安永=第1页01;
    
    //可以直接指定点和线。(注:-e02=e20)
    无功功率,无功功率 指向 = (x个,)=>起源+x个*前任+*安永;
    无功功率,无功功率 线  = (,b,c(c))=>*第1页+b*1个2+c(c)*第1页;
    
    //或者通过join and meet操作。(双楔接,V接。)
    无功功率,无功功率 参加 = (第1页,第2页)=>第1页&第2页;
    无功功率,无功功率 满足 = (l1级,第二语言)=>l1级^第二语言;
    
    //距离和角度
    无功功率,无功功率 dist_points(分布点)     = (第1页,第2页)=>(第1页.标准化(Normalized)&第2页.标准化(Normalized)).长度;
    无功功率,无功功率 dist_point_line(分布点线) = (P(P),)=>((P(P).标准化(Normalized))^(.标准化(Normalized))).2012年第1季度;
    无功功率,无功功率 角度(_L)     = (l1级,第二语言)=>(l1级.标准化(Normalized)<<第二语言.标准化(Normalized)).;
  
    //可以投影和拒绝点和线。
    无功功率,无功功率 项目         = (P(P),)=>P(P)<<*;
    无功功率,无功功率 平行        = (P(P),)=>P(P)<<*P(P);
    无功功率,无功功率 正交的           = (P(P),)=>P(P)<<;
  
    //平移和旋转。
    无功功率,无功功率 转子           = (,P(P))=>数学.余弦(*0.5)+数学.(*0.5)*P(P);
    无功功率,无功功率 翻译      = (x个,)=>1+0.5*(x个*第1页02-*第1页01); 
    
    //为了演示图形,我们创建了一些点和线。
    //用户可以拖动图形中的点,lambda表达式可以
    //用于创建动态更新项。
    无功功率,无功功率 A类 = 指向(-1,-1), B类 = 指向(1,-1), C类 = 指向(-1,1),  = 线(-1,1,0.5);
    
    //Ganja.js可以直接绘制2D PGA元素。传入一个数组
    //要渲染的项。(数字是颜色,字符串是标签,PGA点
    //和行被自动渲染,数组可以用于行
    //线段和多边形)。graph函数返回HTML SVG元素。
    文件.身体.appendChild(附加子项)(.图表([
      //使用数字设置当前颜色。
        0x444444号,
      //字符串标记它们所跟随的项,第一个字符串是标题。
        “标题”,
      //渲染点(用户可以拖动这些点)
        A类, B类, C类, “点的标签”,
      //渲染线
        ,“线条标签”,
      //线段
        ()=>[A类,B类], “段的标签”,
      //多边形
        0x咖啡,
        ()=>[A类,B类,C类], 0xff7777个, “多边形标签”
    ],{栅格:真的, 使有生气:}));
    
    //使用动画模式时,所有lambda的值都将在每帧进行求值。
    //使用Date.now()或类似工具。(咖啡馆里有很多例子。)
});

ganja p2示例

Ganja starterkit:PGA3D P(R*3,0,1)

此示例实现了第15页的表计算机图形学中的冈恩几何代数.我们从上面应用了相同的策略,并从R中的Clifford代数开始3,0,1.

//用3个正生成器和1个零生成器创建一个Clifford代数。
代数(,0,1,()=>{
    
    //将代数信息输出到控制台。
    .描述();
    
    //默认基础为1,e0,e1,e2,e3,e01,e02,e03,e12,e13,e23,e012,e013,e023,e123,e0123
    //向量的度量是0,1,1,1-向量表示平面。
    //双向量的度量为0、0、0,-1、-1,双向量表示直线。
    //三向量的度量为0、0、0和-1-三向量将表示点。
    //伪标量是退化的,所以请使用内置的对偶运算符。
    
    //双矢量由三个电机元件和三个旋转元件组成-
    //在欧几里德空间中表示平移和旋转所需要的确切内容。
    
    //在对偶投影空间中,原点由e12双向量表示。
    无功功率,无功功率 起源=第123页, 前任=-第1页023, 安永=2013年1月, EZ公司=-2012年1月;
    
    //可以直接指定点和平面。
    无功功率,无功功率 指向 = (x个,,z(z))=>起源+x个*前任+*安永+z(z)*EZ公司,
        飞机 = (,b,c(c),d日)=>*第1页+b*1个2+c(c)*1电子3+d日*1个0;
    
    //表摘自“计算机图形的几何代数”第15页
    无功功率,无功功率 线自点            = (P(P),)=>P(P)&,
        平面线            = (,b)=>^b,
        从平面指向           = (,b,c(c))=>^b^c(c),
        平面起点           = (P(P),,)=>P(P)&&,
        距离点到平面          = (,P(P))=>&P(P),
        DistPoints(距离点)                = (P(P),)=>(P(P)&).长度,
        角度平面               = (,b)=>数学.acos公司((<<b).长度),
        每个平面的线通过点 = (P(P),)=>P(P)<<,
        Orth项目指向平面      = (P(P),)=>P(P)<<*,
        平面通过点ParPlane = (P(P),)=>P(P)<<*P(P),
        相交线平面        = (圆周率,)=>圆周率^,
        每条线的平面通过点 = (圆周率,P(P))=>P(P)<<圆周率,
        Orth项目指向线条       = (圆周率,P(P))=>P(P)<<圆周率*圆周率,
        线路通过点ParLine   = (圆周率,P(P))=>P(P)<<圆周率*P(P),
        每行通过点  = (圆周率,P(P))=>(P(P)<<圆周率*P(P))&P(P),
        DistLines(距离线)                 = (圆周率,欧洲药典)=>圆周率&欧洲药典,
        角度线                = (圆周率,欧洲药典)=>数学.acos公司((圆周率<<欧洲药典).长度),
        平面内反射         = (,X(X))=>*X(X)*,
        转子                     = (圆周率,阿尔法)=>数学.余弦(阿尔法/2) + 数学.(阿尔法/2)*圆周率,
        绕直线旋转        = (X(X),圆周率,阿尔法)=>转子(圆周率,阿尔法)*X(X)*~转子(圆周率,阿尔法),
        翻译家                = (x个,,z(z))=>1+0.5*(x个*前任+*安永+z(z)*EZ公司);
    
    //为了演示图形,我们创建了一些点和线。
    //用户可以拖动图形中的点,lambda表达式可以
    //用于创建动态更新项。
    无功功率,无功功率 A类 = 指向(-1,-1, 0), B类 = 指向(1,-1, 0), C类 = 指向(-1,1,0);
    
    //Ganja.js可以直接绘制3D PGA元素。传入一个数组
    //要渲染的项。(数字是颜色,字符串是标签,PGA点
    //和行被自动渲染,数组可以用于行
    //线段和多边形)。graph函数返回HTML SVG元素。
    文件.身体.appendChild(附加子项)(.图表([
      //使用数字设置当前颜色。
        0x444444号,
      //字符串标记它们所跟随的项,第一个字符串是标题。
        “标题”,
      //渲染点(用户可以拖动这些点)
        A类, B类, C类, “点的标签”,
      //渲染线
        ()=>(B类&C类&A类)<<(B类&C类)<<-A类,“线条标签”,
      //线段
        ()=>[A类,B类], “段的标签”,
      //多边形
        0x咖啡,
        ()=>[A类,B类,C类], 0xff7777个, “多边形标签”
    ],{栅格:, 使有生气:}));
    
    //使用动画模式时,所有lambda的值都将在每帧进行求值。
    //使用Date.now()或类似工具。(咖啡馆里有很多例子。)
});

ganja p3示例