第065封“情书”:时间旅行Visualizing RecamánSequenceVEX<Entagma>Houdini2018

█世俗如此强大,让你误以为世俗就是真实的。当你被他人禁锢时,当你被世俗左右时,当你被现实打击时,你变得彷徨,迷茫和沮丧。穿越时间的长河,才能看清什么对生命是最重要的。— 每天翻译一篇教程,这就是我写给houdini的情书。【首发于同名公众号:“致houdini的情书”】



█ 时空隧道?


前言不搭后语:

  年轻时想要快点成熟远离稚嫩;但当生活的压力扑面而来时,又想回到单纯快乐的时光。这时就会开始做不切实际的穿越梦。

    圆方,你怎么看?


今天这节内容:

    如何使用一个列表公式连线



这一节要实现的效果

20180702A Tribute To Numberphile- Visualizing Recamán's Sequence in VEX2.png


▉今天是42岁第039天周一

这是写给houdini的

第065封“情书”

我是geo流程图

blob.png

我是vex代码

构建"点序列画出半圆弧线

   

    //------------构建推荐序列-----------------

    

    int numiter = chi(“Iterations”);

    

    int sequence[];

    

    push(sequence,0);

    

    //-- 4 循环—

    for(int n=1; n <= numiter; n++){

        int a = sequence[n-1]-n;

        if(a>0 && find(sequence,a)<0){  

        } 

        else{

            a = sequence[n-1] + n;

        }

        push(sequence, a);

        

    }

    i[]@sequence = sequence;


int subdivs = chi(“Subdivisions”);   

int sequence[] = i[]@sequence;   



int prevnumber = 0; 


float prevdist = 0;  


int dir = 1;



foreach(int a; sequence){  


    if(a>0){

       

        float dist = a- prevnumber;

        

        if(dist>0 && prevdist >0) 

            dir = -1;

        if(dist<0 && prevdist <0) 

            dir = -1; 

        

        

        float radius = dist0.5;

        

        vector ctr = set(a-radius,0,0); 

        

        //---------使用“中心点”“半径”产生形成半圆的中间点----------        

        int pts[];

       

        float angleincrement = PI / float(subdivs);

       

        for(float angle = 0; angle <= PI; angle += angleincrement){

            float x = cos(angle) radius;

            float y = sin(angle)* radius* dir;

            vector offset = set(x,y,0); // 偏移量

            vector pos = ctr + offset;

            

          

            int newpt = addpoint(0,pos);

            push(pts,newpt);           

        }

        addprim(0,“polyline”,pts);

        

        prevdist = dist;

    }

    prevnumber = a; 


}

本节主要步骤:


A

创建Recaman序列


两个判断条件求正确的a(n)点序列

(一)两种条件:a(n)=a(n-1)-n

    1)“往回跳”成立时:a(n)>0,执行a(n)公式

blob.png

    2)“往前跳”成立时:a(n)<0,执行a(n)=序列[n-1]+n

blob.png

 (二)把a放入列表sequencepush(sequence, a)

 (三)把序列放入列表属性i[]@sequence = sequence


B

将序列点连接成圆弧线条

1 引入 prevnumber prevdist

2 同方向跳跃两次作为判断条件创建翻转弧度变量dir

3 画出半圆圆弧

    a)变量: 1)点数列表int pts[];2)角度增量变量angleincrement = PI / float(subdivs);

    b)for循环在180度内,逐步增加角度增量,结合余弦正弦画出点位置:1)float x = cos(angle)* radius;2)float y = sin(angle)* radius* dir;3)偏移vector offset = set(x,y,0);4)点位置vector pos = ctr + offset;5)增加半圆点int newpt = addpoint(0,pos);6)放入列表push(pts,newpt); 7)增加连线addprim(0,“polyline”,pts);  8)更新变量“前距离”prevdist = dist; “前数字”prevnumber = a

首先

原理部分

Recaman

雷卡曼

序列

起始

所有的故事都是从一条从0开始的整数数字线开始;

image.png

原理

1)根据一个逐次加一的迭代值N;每次从数字A“首先向后”跳“N个数值”到数字B。

2)判断是否成立,

    a)成立(从B再向前跳N+1个数值);

    b)不成立(从A向前跳N+1个数值)如此循环;




模型具体运算过程




<第一次迭代> 数字“0”  

image.png

“0”的位置,迭代值n=1

1)第一次迭代值n=1

      第一件事:“向后1步”,到达数字=负值【而负值不被允许】

      第二件事:“向前1步”,到达数字=“1”




<第二次迭代> 数字“1”

image.png

“1”的位置,迭代值n=2


2)第二次迭代值n=2

      第一件事:“向后2步”;到达数字=负值【不被允许】

      第二件事:“向前2步”:到达数字=“3”




<第三次迭代> 数字“3”

image.png

来到“3”的位置。


3)第三次迭代值n=3,

      第一件事, “向后3步” :得到数值=0 【0曾经访问过也不被允许】

      第二件事: “向前3步” :到达数字=“6”




<第四次迭代> 数字“6”

 image.png

来到“6”的位置。


4)第四次迭代值n=4,

      第一件事, “向后4步” 。数值=2

      第二件事: 此时迭代值n=4结束,从“2” “向前5步”到达数字“7”




<第五次迭代>  数字“2”

image.png

来到“2”的位置



5)“2”:第五次迭代值n=5,

    第一件事, “向后5步” 。数值=负值

    第二件事, “向前5步” 。数值=7




<第六次迭代> 数字“7”

image.png

来到“7”的位置


6)“7”:第六次迭代值n=6,

    第一件事, “向后6步” 。数值=1(访问过,不被允许)

    第二件事, “向前6步” 。数值=13


总结

结构与规律

image.png

1。当同一方向上进行两次连续跳跃后,翻转“弧度的方向”

image.png

2。所以只需要检查是否在同一方向上连续跳跃两次;然后翻转红线部分;



接下来

开始正式制作

使用软件houdini16.5 


recaman序列公式



整数序列的在线百科全书网站

recaman’s 序列:oeis.org/A005132  这里归档了数字序列;以及如何它们构造 。

 公式

a(0) = 0; for n > 0, a(n) = a(n-1) - n if positive and not already in the sequence, otherwise a(n) = a(n-1) + n. 

1)如果是正值,并且没有出现自序列中 

a(n) = a(n-1) – n,

否则otherwise

a(n) = a(n-1) + n. 

image.png



首先构建"点序列"

1) attributwrangle1  //  Run Over:Detail(only once)

    a) Iteration=32


首先

构造一个数字序列[0,1,3,6,3,7,13…]


1)选择运行一次: 设定迭代值Iteration=32


//------------构建推荐序列-----------------


//-- 1  迭代值

int numiter = chi(“Iterations”);


//-- 2  存储将要生成数字的序列

int sequence[];


//-- 3   迭代跳跃前 初始化一些条件

//-- 3a 首先 序列中的第一个数0

push(sequence,0);


//-- 4 在迭代值内进行循环

for(int n=1; n <= numiter; n++){

    //-- 4-1  套用recaman公式 

a(0) = 0; 

for n > 0, a(n) = a(n-1) - n 

if positive and not already in the sequence, 

otherwise a(n) = a(n-1) + n. 

    int a = sequence[n-1]-n;

    //-- 4-2 find函数判断a是否存在于列表中,没有找到返回-1//-------------------------“往回跳跃

    if(a>0 && find(sequence,a)<0){

blob.png

(满足“往回跳跃”条件:a(n-1)>a(n)&& a不在序列中)

    } 

 //-------------------------“往前跳跃

blob.png

   else{

        a = sequence[n-1] + n;

    }

    //-- 4-3 将a添加进列表,a就是正确的点序号

    push(sequence, a);

    

}

//-- 5 把序列作为detail属性来写

i[]@sequence = sequence;


问题)如何画“弧线”

image.png

分析)比如从2到7这段弧线;需要知道“中心点”“半径”


3 找到弧度 中心点和半径

2) attributwrangle1  //  Run Over:Detail(only once)

//Subdivisions=64  

image.png

2)通过两点之间的距离dist,可以同时找到“中心点”和“半径”

    a)半径= dist/2 或 dist0.5 

    b)中心点=目标点-半径

    c)正弦和余弦生成半圆;


//---------------------准备工作---------------------


//-- 1 细分变量 

int subdivs = chi(“Subdivisions”);  

//-- 2 导入detail-列表属性 

int sequence[] = i[]@sequence;   


//float PI = 3.1415926;

//-- 在迭代列表数字之前,之前的点已经存储的几个变量;初始化之前的数字  

int prevnumber = 0; 


4 翻转弧度变量dir


//-- 当我们决定是否翻转一个半圆;在相同的方向走第二步时;需要存储之前跳转的距离。把它存储到prevdist中;

float prevdist = 0; 


//-- 判断方向,在轴之上,还是轴之下;

int dir = 1;//另一个方向就是-1; 


//----------------开始工作:迭代列表中的数值---------- 

//-- 每次迭代,从列表中取出一个值,写进a中

foreach(int a; sequence){  


    if(a>0){

        //-- 先检查一下距离;

        float dist = a- prevnumber;

        //-- 同一方向,迈出第二步的,圆弧朝向

blob.png

        if(dist>0 && prevdist >0) //dist>0=当前点“向前跳”prevdist >0=前一个点“向前跳”当前圆弧在轴之上

            dir = -1; //翻转

blob.png

        if(dist<0 && prevdist <0) 

            dir = -1; 

        blob.png

        //-- 半径 翻转(连续两段)

        float radius = dist0.5;

        //-- 标出半圆的中心

        vector ctr = set(a-radius,0,0); 

        

画出半圆弧度


        //---------使用“中心点”“半径”正弦余弦产生形成[半圆]的中间点----------  

        //---------使用三角函数形成直线

        int pts[];

        //-- 画出一个圆每一步的角度;角度增量,迭代值越大,细分间隔角度越小

        float angleincrement = PI / float(subdivs);

        //-- for循环画出这些点的坐标,迭代一个浮点角度从0开始,计算半圆上各个位置

        for(float angle = 0; angle <= PI; angle += angleincrement){




        //-- 确定点的位置

            float x = cos(angle) radius;

            float y = sin(angle) radius* dir;

            vector offset = set(x,y,0); // 偏移量

            vector pos = ctr + offset;

            



            //-- 创建半圆的点

            int newpt = addpoint(0,pos);

            //--  把点增加到点列表

            push(pts,newpt);           

        }



        addprim(0,“polyline”,pts);

        //-- 必须更新prevdist,下一次迭代使用

        prevdist = dist;

    }

    prevnumber = a


attribwrangle1的“迭代”

attribwrangle2的“细分”

blob.png

“迭代”=48;“细分”=64

blob.png“迭代”=140“细分”=64

blob.png

“迭代”=48;“细分”=3

blob.png

“迭代”=48;“细分”=2

今天就到这儿了,收功

教程翻译自entagma的网络教程

下一节:xx

微信图片_20190607085947.jpg

     本文图片全部原创,版权归原作者所有

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值