jjzjj

javascript - 根据管端法线将旋转应用于圆柱体

coder 2025-01-11 原文

我正在尝试在three.js中制作弯曲的3D箭头。为了完成此任务,我创建了一个沿着弯曲路径的Tube和一个形状为圆锥形的Cylinder(通过将radiusTop设置为微小)。他们目前看起来像这样:





我试图将箭头头(圆柱体为圆锥形)放置在电子管的末端,如下所示:(Photoshopped)



我的数学不是很强,对three.js还是很陌生。有人可以帮助我了解如何将两者连接起来吗?

这是我当前的代码:

        import T from 'three';

        var findY = function(r, x)
        {
           return Math.sqrt((r * r) - (x * x));
        }

        var radius = 25;
        var x = 0;
        var z = 0;
        var numberOfPoints = 10;
        var interval =  (radius/numberOfPoints);
        var points = [];

        for (var i = numberOfPoints; i >= 0; i--) 
        {
           var y = findY(radius, x);
           points.push(new T.Vector3(x, y, z))
           x = x + interval;
        }

        x = x - interval;

        for (var i = numberOfPoints - 1 ; i >= 0; i--) 
        {
           y = findY(radius, x) * -1;
           points.push(new T.Vector3(x, y, z));
           x = x - interval;
        }

        var path = new T.CatmullRomCurve3(points);

        var tubeGeometry = new T.TubeGeometry(
            path,  //path
            10,    //segments
            radius / 10,     //radius
            8,     //radiusSegments
            false  //closed
        );

        var coneGeometry = new T.CylinderGeometry(
            radiusTop = 0.1,
            radiusBottom = radius/5,
            height = 10,
            radialSegments = 10,
            heightSegments = 10,
            openEnded = 1
        );

        var material = new T.MeshBasicMaterial( { color: 0x00ff00 } );

        var tube = new T.Mesh( tubeGeometry, material );
        var cone = new T.Mesh( coneGeometry, material );

        // Translate and Rotate cone?

如果有人可以尝试简单地解释数学和程序上需要完成的工作,我将不胜感激
  • 查找位于试管末端的法线
  • 将锥体移到正确的位置

  • 任何帮助表示赞赏!

    最佳答案

    当您可以直接在适当位置创建箭头时,请勿为此使用旋转。同样,弯曲的管子也可以用这种方法完成。您只需要它是A,B端点定义的最后一个线段。

    A为尖点,让B为光盘的中心。要创建箭头,您需要2个附加基向量,将它们称为基础光盘的U,V和radius r。通过它们,您可以使用简单的圆形公式创建圆盘点,如下所示:


  • 获取AB端点
  • 计算U,V基本向量
    U,V应该位于箭头的光盘基部中,并且应该彼此垂直。箭头的方向(线|BA|)是圆盘的法线,因此利用叉积,该乘积将垂直向量返回到乘积,因此:
    W = B-A;
    W /= |W|;    // unit vector
    T = (1,0,0); // temp any non zero vector not parallel to W
    if ( |(W.T)|>0.75 ) T = (0,1,0); // if abs dot product of T and W is close to 1 it means they are close to parallel so chose different T
    U = (T x W) // U is perpendicular to T,W
    V = (U x W) // V is perpendicular to U,W
    
  • 创建/渲染箭头几何

    这很容易,A,B是三 Angular 形扇形的中心(需要2),并且光盘基点的计算如下:
    P(ang) = B + U.r.cos(ang) + V.r.sin(ang)
    

    因此,只需一步步就将ang循环遍历整个圆圈,这样您就可以获得足够的点数(通常36个点就足够了),并从中进行两个三 Angular 形的扇形处理。不要忘记最后一个光盘点必须与第一个光盘点相同,否则ang = 0360 deg上会出现难看的外观或孔洞。

  • 如果您仍然想旋转,则可以这样做。以与上述相同的方式计算U,V,W,并从中构造出转换矩阵。原点O将为点B,轴X,Y,Z将为U,V,W,其顺序取决于您的箭头模型。 W应该与模型轴匹配。 U,V可以采用任何顺序。因此,只需将所有矢量复制到它们的位置,然后使用此矩阵进行渲染即可。有关更多信息,请参见:
  • Understanding 4x4 homogenous transform matrices

  • [说明]

    如果您不知道如何计算矢量运算,例如叉/点积或绝对值,请参阅:
    // cross product: W = U x V
    W.x=(U.y*V.z)-(U.z*V.y)
    W.y=(U.z*V.x)-(U.x*V.z)
    W.z=(U.x*V.y)-(U.y*V.x)
    // dot product: a = (U.V)
    a=U.x*V.x+U.y*V.y+U.z*V.z
    // abs of vector a = |U|
    a=sqrt((U.x*U.x)+(U.y*U.y)+(U.z*U.z))
    

    [Edit1]简单的GL实现

    我不在您的环境中编写代码,但由于downvote和评论建议您无法将它们自己组合在一起,考虑到您已经做到了这一点,这很奇怪,因此在这里,简单的 C++/GL 示例如何做到这一点(您可以将其移植到您的环境中):


    void glArrowRoundxy(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat a2)
        {
        const int _glCircleN=50;    // points per circle
        const int n=3*_glCircleN;
        int i,j,ix,e;
        float x,y,z,x1,y1,z1,a,b,da,db=pi2/(_glCircleN-1);
        float ux,uy,uz,vx,vy,vz,u,v;
        // buffers
        GLfloat ptab[6*_glCircleN],*p0,*p1,*n0,*n1,*p;
        p0=ptab+(0*_glCircleN);     // previous tube segment circle points
        p1=ptab+(3*_glCircleN);     // actual tube segment circle points
        da=+db; if (a0>a1) da=-db;  // main angle step direction
        ux=0.0;                     // U is normal to arrow plane
        uy=0.0;
        uz=1.0;
        // arc interpolation a=<a0,a1>
        for (e=1,j=0,a=a0;e;j++,a+=da)
            {
            // end conditions
            if ((da>0.0)&&(a>=a1)) { a=a1; e=0; }
            if ((da<0.0)&&(a<=a1)) { a=a1; e=0; }
            // compute actual tube ceneter
            x1=x0+(r*cos(a));
            y1=y0+(r*sin(a));
            z1=z0;
            // V is direction from (x0,y0,z0) to (x1,y1,z1)
            vx=x1-x0;
            vy=y1-y0;
            vz=z1-z0;
            // and unit of coarse
            b=sqrt((vx*vx)+(vy*vy)+(vz*vz));
            if (b>1e-6) b=1.0/b; else b=0.0;
            vx*=b;
            vy*=b;
            vz*=b;
            // tube segment
            for (ix=0,b=0.0,i=0;i<_glCircleN;i++,b+=db)
                {
                u=r0*cos(b);
                v=r0*sin(b);
                p1[ix]=x1+(ux*u)+(vx*v); ix++;
                p1[ix]=y1+(uy*u)+(vy*v); ix++;
                p1[ix]=z1+(uz*u)+(vz*v); ix++;
                }
            if (!j)
                {
                glBegin(GL_TRIANGLE_FAN);
                glVertex3f(x1,y1,z1);
                for (ix=0;ix<n;ix+=3) glVertex3fv(p1+ix);
                glEnd();
                }
            else{
                glBegin(GL_QUAD_STRIP);
                for (ix=0;ix<n;ix+=3)
                    {
                    glVertex3fv(p0+ix);
                    glVertex3fv(p1+ix);
                    }
                glEnd();
                }
            // swap buffers
            p=p0; p0=p1; p1=p;
            p=n0; n0=n1; n1=p;
            }
        // arrowhead a=<a1,a2>
        for (ix=0,b=0.0,i=0;i<_glCircleN;i++,b+=db)
            {
            u=r1*cos(b);
            v=r1*sin(b);
            p1[ix]=x1+(ux*u)+(vx*v); ix++;
            p1[ix]=y1+(uy*u)+(vy*v); ix++;
            p1[ix]=z1+(uz*u)+(vz*v); ix++;
            }
        glBegin(GL_TRIANGLE_FAN);
        glVertex3f(x1,y1,z1);
        for (ix=0;ix<n;ix+=3) glVertex3fv(p1+ix);
        glEnd();
        x1=x0+(r*cos(a2));
        y1=y0+(r*sin(a2));
        z1=z0;
        glBegin(GL_TRIANGLE_FAN);
        glVertex3f(x1,y1,z1);
        for (ix=n-3;ix>=0;ix-=3) glVertex3fv(p1+ix);
        glEnd();
        }
    

    这将在XY平面中使用中心x,y,z和大半径r渲染弯曲的箭头。 r0是管半径,而r1是箭头基准半径。由于没有您的曲线定义,因此我选择了XY平面中的圆。 a0,a1,a2是箭头开始(a0),箭头开始(a1)和结束(a2)的 Angular 。 pi2只是常量pi2=6.283185307179586476925286766559

    这个想法是要记住实际的和先前的管段圆点,因此ptab,p0,p1在那里,否则您将需要计算两次所有内容。

    当我直接选择XY平面时,我知道一个基本向量垂直于它。第二个是垂直于箭头并且垂直于箭头方向的,幸运的是,圆形属性本身就提供了此功能,因此在这种情况下不需要叉积。

    希望如果不对我发表评论,就已经足够清楚了。

    [Edit2]

    我需要将其添加到我的引擎中,所以这里是3D版本(不仅限于轴对齐的箭头,而且圆锥体也弯曲了)。除了基本矢量计算之外,其他操作都是相同的,我还更改了 header 中的 Angular <a0,a1>是整个区间,aa是箭头大小,但在后者中,它将转换为原始约定。我还为照明计算添加了法线。我还添加了线性箭头,如果您得到不同的曲线,则基矢量的计算不利用圆的属性。结果如下:
    //---------------------------------------------------------------------------
    const int _glCircleN=50;    // points per circle
    //---------------------------------------------------------------------------
    void glCircleArrowxy(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat aa)
        {
        double pos[3]={ x0, y0, z0};
        double nor[3]={0.0,0.0,1.0};
        double bin[3]={1.0,0.0,0.0};
        glCircleArrow3D(pos,nor,bin,r,r0,r1,a0,a1,aa);
        }
    //---------------------------------------------------------------------------
    void glCircleArrowyz(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat aa)
        {
        double pos[3]={ x0, y0, z0};
        double nor[3]={1.0,0.0,0.0};
        double bin[3]={0.0,1.0,0.0};
        glCircleArrow3D(pos,nor,bin,r,r0,r1,a0,a1,aa);
        }
    //---------------------------------------------------------------------------
    void glCircleArrowxz(GLfloat x0,GLfloat y0,GLfloat z0,GLfloat r,GLfloat r0,GLfloat r1,GLfloat a0,GLfloat a1,GLfloat aa)
        {
        double pos[3]={ x0, y0, z0};
        double nor[3]={0.0,1.0,0.0};
        double bin[3]={0.0,0.0,1.0};
        glCircleArrow3D(pos,nor,bin,r,r0,r1,a0,a1,aa);
        }
    //---------------------------------------------------------------------------
    void glCircleArrow3D(double *pos,double *nor,double *bin,double r,double r0,double r1,double a0,double a1,double aa)
        {
    //  const int _glCircleN=20;    // points per circle
        int e,i,j,N=3*_glCircleN;
        double U[3],V[3],u,v;
        double a,b,da,db=pi2/double(_glCircleN-1),a2,rr;
        double *ptab,*p0,*p1,*n0,*n1,*pp,p[3],q[3],c[3],n[3],tan[3];
        // buffers
        ptab=new double [12*_glCircleN]; if (ptab==NULL) return;
        p0=ptab+(0*_glCircleN);
        n0=ptab+(3*_glCircleN);
        p1=ptab+(6*_glCircleN);
        n1=ptab+(9*_glCircleN);
        // prepare angles
        a2=a1; da=db; aa=fabs(aa);
        if (a0>a1) { da=-da; aa=-aa; }
        a1-=aa;
        // compute missing basis vectors
        vector_copy(U,nor);         // U is normal to arrow plane
        vector_mul(tan,nor,bin);    // tangent is perpendicular to normal and binormal
        // arc interpolation a=<a0,a2>
        for (e=0,j=0,a=a0;e<5;j++,a+=da)
            {
            // end conditions
            if (e==0)   // e=0
                {
                if ((da>0.0)&&(a>=a1)) { a=a1; e++; }
                if ((da<0.0)&&(a<=a1)) { a=a1; e++; }
                rr=r0;
                }
            else{       // e=1,2,3,4
                if ((da>0.0)&&(a>=a2)) { a=a2; e++; }
                if ((da<0.0)&&(a<=a2)) { a=a2; e++; }
                rr=r1*fabs(divide(a-a2,a2-a1));
                }
            // compute actual tube segment center c[3]
            u=r*cos(a);
            v=r*sin(a);
            vector_mul(p,bin,u);
            vector_mul(q,tan,v);
            vector_add(c,p,  q);
            vector_add(c,c,pos);
            // V is unit direction from arrow center to tube segment center
            vector_sub(V,c,pos);
            vector_one(V,V);
            // tube segment interpolation
            for (b=0.0,i=0;i<N;i+=3,b+=db)
                {
                u=cos(b);
                v=sin(b);
                vector_mul(p,U,u);      // normal
                vector_mul(q,V,v);
                vector_add(n1+i,p,q);
                vector_mul(p,n1+i,rr);  // vertex
                vector_add(p1+i,p,c);
                }
            if (e>1)                    // recompute normals for cone
                {
                for (i=3;i<N;i+=3)
                    {
                    vector_sub(p,p0+i  ,p1+i);
                    vector_sub(q,p1+i-3,p1+i);
                    vector_mul(p,p,q);
                    vector_one(n1+i,p);
                    }
                vector_sub(p,p0    ,p1);
                vector_sub(q,p1+N-3,p1);
                vector_mul(p,q,p);
                vector_one(n1,p);
                if (da>0.0) for (i=0;i<N;i+=3) vector_neg(n1+i,n1+i);
                if (e==  3) for (i=0;i<N;i+=3) vector_copy(n0+i,n1+i);
                }
            // render base disc
            if (!j)
                {
                vector_mul(n,U,V);
                glBegin(GL_TRIANGLE_FAN);
                glNormal3dv(n);
                glVertex3dv(c);
                if (da<0.0) for (i=N-3;i>=0;i-=3) glVertex3dv(p1+i);
                else        for (i=  0;i< N;i+=3) glVertex3dv(p1+i);
                glEnd();
                }
            // render tube
            else{
                glBegin(GL_QUAD_STRIP);
                if (da<0.0) for (i=0;i<N;i+=3)
                    {
                    glNormal3dv(n1+i); glVertex3dv(p1+i);
                    glNormal3dv(n0+i); glVertex3dv(p0+i);
                    }
                else for (i=0;i<N;i+=3)
                    {
                    glNormal3dv(n0+i); glVertex3dv(p0+i);
                    glNormal3dv(n1+i); glVertex3dv(p1+i);
                    }
                glEnd();
                }
            // swap buffers
            pp=p0; p0=p1; p1=pp;
            pp=n0; n0=n1; n1=pp;
            // handle r0 -> r1 edge
            if (e==1) a-=da;
            if ((e==1)||(e==2)||(e==3)) e++;
            }
        // release buffers
        delete[] ptab;
        }
    //---------------------------------------------------------------------------
    void glLinearArrow3D(double *pos,double *dir,double r0,double r1,double l,double al)
        {
    //  const int _glCircleN=20;    // points per circle
        int e,i,N=3*_glCircleN;
        double U[3],V[3],W[3],u,v;
        double a,da=pi2/double(_glCircleN-1),r,t;
        double *ptab,*p0,*p1,*n1,*pp,p[3],q[3],c[3],n[3];
        // buffers
        ptab=new double [9*_glCircleN]; if (ptab==NULL) return;
        p0=ptab+(0*_glCircleN);
        p1=ptab+(3*_glCircleN);
        n1=ptab+(6*_glCircleN);
        // compute basis vectors
        vector_one(W,dir);
        vector_ld(p,1.0,0.0,0.0);
        vector_ld(q,0.0,1.0,0.0);
        vector_ld(n,0.0,0.0,1.0);
        a=fabs(vector_mul(W,p));            pp=p; t=a;
        a=fabs(vector_mul(W,q)); if (t>a) { pp=q; t=a; }
        a=fabs(vector_mul(W,n)); if (t>a) { pp=n; t=a; }
        vector_mul(U,W,pp);
        vector_mul(V,U,W);
        vector_mul(U,V,W);
        for (e=0;e<4;e++)
            {
            // segment center
            if (e==0) { t=0.0;  r= r0; }
            if (e==1) { t=l-al; r= r0; }
            if (e==2) { t=l-al; r= r1; }
            if (e==3) { t=l;    r=0.0; }
            vector_mul(c,W,t);
            vector_add(c,c,pos);
            // tube segment interpolation
            for (a=0.0,i=0;i<N;i+=3,a+=da)
                {
                u=cos(a);
                v=sin(a);
                vector_mul(p,U,u);      // normal
                vector_mul(q,V,v);
                vector_add(n1+i,p,q);
                vector_mul(p,n1+i,r);   // vertex
                vector_add(p1+i,p,c);
                }
            if (e>2)                    // recompute normals for cone
                {
                for (i=3;i<N;i+=3)
                    {
                    vector_sub(p,p0+i  ,p1+i);
                    vector_sub(q,p1+i-3,p1+i);
                    vector_mul(p,p,q);
                    vector_one(n1+i,p);
                    }
                vector_sub(p,p0    ,p1);
                vector_sub(q,p1+N-3,p1);
                vector_mul(p,q,p);
                vector_one(n1,p);
                }
            // render base disc
            if (!e)
                {
                vector_neg(n,W);
                glBegin(GL_TRIANGLE_FAN);
                glNormal3dv(n);
                glVertex3dv(c);
                for (i=0;i<N;i+=3) glVertex3dv(p1+i);
                glEnd();
                }
            // render tube
            else{
                glBegin(GL_QUAD_STRIP);
                for (i=0;i<N;i+=3)
                    {
                    glNormal3dv(n1+i);
                    glVertex3dv(p0+i);
                    glVertex3dv(p1+i);
                    }
                glEnd();
                }
            // swap buffers
            pp=p0; p0=p1; p1=pp;
            }
        // release buffers
        delete[] ptab;
        }
    //---------------------------------------------------------------------------
    

    用法:
    glColor3f(0.5,0.5,0.5);
    
    glCircleArrowyz(+3.5,0.0,0.0,0.5,0.1,0.2,0.0*deg,+270.0*deg,45.0*deg);
    
    glCircleArrowyz(-3.5,0.0,0.0,0.5,0.1,0.2,0.0*deg,-270.0*deg,45.0*deg);
    glCircleArrowxz(0.0,+3.5,0.0,0.5,0.1,0.2,0.0*deg,+270.0*deg,45.0*deg);
    glCircleArrowxz(0.0,-3.5,0.0,0.5,0.1,0.2,0.0*deg,-270.0*deg,45.0*deg);
    glCircleArrowxy(0.0,0.0,+3.5,0.5,0.1,0.2,0.0*deg,+270.0*deg,45.0*deg);
    glCircleArrowxy(0.0,0.0,-3.5,0.5,0.1,0.2,0.0*deg,-270.0*deg,45.0*deg);
    glColor3f(0.2,0.2,0.2);
    glLinearArrow3D(vector_ld(+2.0,0.0,0.0),vector_ld(+1.0,0.0,0.0),0.1,0.2,2.0,0.5);
    glLinearArrow3D(vector_ld(-2.0,0.0,0.0),vector_ld(-1.0,0.0,0.0),0.1,0.2,2.0,0.5);
    glLinearArrow3D(vector_ld(0.0,+2.0,0.0),vector_ld(0.0,+1.0,0.0),0.1,0.2,2.0,0.5);
    glLinearArrow3D(vector_ld(0.0,-2.0,0.0),vector_ld(0.0,-1.0,0.0),0.1,0.2,2.0,0.5);
    glLinearArrow3D(vector_ld(0.0,0.0,+2.0),vector_ld(0.0,0.0,+1.0),0.1,0.2,2.0,0.5);
    glLinearArrow3D(vector_ld(0.0,0.0,-2.0),vector_ld(0.0,0.0,-1.0),0.1,0.2,2.0,0.5);
    

    和长尾概述(在图像的右侧):



    我正在使用我的向量库,所以这里有一些解释:
    vector_mul(a[3],b[3],c[3])是跨产品a = b x cvector_mul(a[3],b[3],c)是标量a = b.c的简单乘法a = vector_mul(b[3],c[3])是点积a = (b.c)vector_one(a[3],b[3])是单位向量a = b/|b|vector_copy(a[3],b[3])只是复制a = bvector_add(a[3],b[3],c[3])正在添加a = b + cvector_sub(a[3],b[3],c[3])减去a = b - cvector_neg(a[3],b[3])是否定a = -bvector_ld(a[3],x,y,z)刚刚加载a = (x,y,z)pos是圆圈箭头的中心位置,而nor是箭头所在平面的法线。 bin是双法线,并且 Angular 从该轴开始。应该垂直于norr,r0,r1是箭头的半径(弯曲,管状,圆锥形)

    线性箭头类似,dir是箭头的方向,l是箭头的大小,al是箭头的大小。

    关于javascript - 根据管端法线将旋转应用于圆柱体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39665459/

    有关javascript - 根据管端法线将旋转应用于圆柱体的更多相关文章

    1. ruby - 将差异补丁应用于字符串/文件 - 2

      对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

    2. ruby-on-rails - Rails 应用程序之间的通信 - 2

      我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

    3. ruby - 无法运行 Rails 2.x 应用程序 - 2

      我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

    4. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

      刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

    5. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

      我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

    6. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

      我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

    7. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

      是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

    8. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

      无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

    9. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

      导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

    10. 旋转矩阵的几何意义 - 2

      点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

    随机推荐