将希尔伯特值映射到3D点

时间:2009-01-31 17:28:42

标签: algorithm math hilbert-curve

我有一组希尔伯特值(从Hilbert curve开始到给定点的长度)。

将这些值转换为3D点的最佳方法是什么?原始希尔伯特曲线不是3D,所以我想我必须自己选择我需要的希尔伯特曲线等级。我确实有总曲线长度(即,集合中的最大值)。

也许现有的实施?一些库可以让我使用希尔伯特曲线/值?语言并不重要。

2 个答案:

答案 0 :(得分:3)

不是关于3D转换的答案,但这里有一个很好的算法和Hilbert值的讨论Two-dimensional spatial hashing with space-filling curves

来自MIT

4 algorithms for the n-dimensional Hilbert Space-Filling Curve

* A. R. Butz, "Alternative Algorithm for Hilbert's Space-Filling Curve",
  IEEE Trans. Comp., April, 1971, pp 424-426. [Butz 1971]

* S. W. Thomas, "hilbert.c" in the Utah Raster Toolkit circa 1993,
  http://web.mit.edu/afs/athena/contrib/urt/src/urt3.1/urt-3.1b.tar.gz

* D. Moore, Fast Hilbert Curves in C, without Recursion

* J.K.Lawder, Calculation of Mappings Between One and n-dimensional Values Using the Hilbert Space-filling Curve, [JL1_00]

答案 1 :(得分:1)

如果我的问题是正确的,那么从希尔伯特3D曲线的起点开始,你有一些曲线距离 <div class="row"> <div class="col-12" > <div class="row"> <div class="col-3"> <img src="..." alt=""> </div> <div class="col-9"> <h3>Headline 1</h3> <p>"Lorem ipsum dolor sit amet, ... </p> </div> </div> </div> <div class="col-12" > <div class="row"> <div class="col-3"> <img src="..." alt=""> </div> <div class="col-9"> <h3>Headline 2</h3> <p>"Lorem ipsum dolor sit amet, ... </p> </div> </div> </div> <div class="col-12" > <div class="row"> <div class="col-3"> <img src="..." alt=""> </div> <div class="col-9"> <h3>Headline 3</h3> <p>"Lorem ipsum dolor sit amet, ... </p> </div> </div> </div> </div> ,并希望得到与这一点相对应的坐标。

如果您将整个 3D希尔伯特曲线(覆盖单位立方体)预生成为折线,则所有测序点在前一点和下一点之间的距离相同。因此,您可以使用piecewise linear interpolation计算您的观点。

这就是我在 C ++ 中生成和渲染 2D / 3D希尔伯特曲线的方法:

l

我使用了我的动态列表模板,所以:


//--------------------------------------------------------------------------- #ifndef _Hilbert_vector_h #define _Hilbert_vector_h //--------------------------------------------------------------------------- #include "list.h" //--------------------------------------------------------------------------- void Hilbert2D(List<double> &pnt,double x,double y,double z,double a,int n) { int i,j,m; double x0,y0,x1,y1,q; for (m=4*3,i=1,j=2;j<=n;j++,i+=i+1) m*=4; a/=i; // m = needed size of pnt[] pnt.num=0; // init generator pnt.add(x); pnt.add(y); pnt.add(z); y+=a; pnt.add(x); pnt.add(y); pnt.add(z); x+=a; pnt.add(x); pnt.add(y); pnt.add(z); y-=a; pnt.add(x); pnt.add(y); pnt.add(z); x0=x-0.5*a; // center of generator y0=y+0.5*a; // iterative subdivision for (j=2;j<=n;j++) { // mirror/rotate 2 qudrants x1=x0; y1=y0; m=pnt.num; for (i=m;i>=3;) { i--; z=pnt.dat[i] ; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; q=x; x=+y; y=-q; // z+ pnt.dat[i+0]=(x1+x); pnt.dat[i+1]=(y1-y); pnt.dat[i+2]=( z); } for (y1+=2.0*a,i=m;i>=3;) { i--; z=pnt.dat[i] ; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; q=x; x=-y; y=+q; // z- pnt.add(x1+x); pnt.add(y1+y); pnt.add( z); } // mirror the rest x0+=a; y0+=a; m=pnt.num; for (i=m;i>=3;) { i--; z=pnt.dat[i] ; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; pnt.add(x0-x); pnt.add(y0+y); pnt.add( z); } a*=2.0; } /* // rotations q=x; x=+y; y=-q; // z+ q=x; x=-y; y=+q; // z- */ } //--------------------------------------------------------------------------- void Hilbert3D(List<double> &pnt,double x,double y,double z,double a,int n) { int i,j,m; double x0,y0,z0,x1,y1,z1,q; for (m=8*3,i=1,j=2;j<=n;j++,i+=i+1) m*=8; a/=i; // m = needed size of pnt[] pnt.num=0; // init generator pnt.add(x); pnt.add(y); pnt.add(z); z-=a; pnt.add(x); pnt.add(y); pnt.add(z); x+=a; pnt.add(x); pnt.add(y); pnt.add(z); z+=a; pnt.add(x); pnt.add(y); pnt.add(z); y+=a; pnt.add(x); pnt.add(y); pnt.add(z); z-=a; pnt.add(x); pnt.add(y); pnt.add(z); x-=a; pnt.add(x); pnt.add(y); pnt.add(z); z+=a; pnt.add(x); pnt.add(y); pnt.add(z); x0=x+0.5*a; // center of generator y0=y-0.5*a; z0=z-0.5*a; // iterative subdivision for (j=2;j<=n;j++) { // mirror/rotate qudrants x1=x0; y1=y0; z1=z0; m=pnt.num; for (i=m;i>=3;) { i--; z=pnt.dat[i]-z0; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; q=y; y=-z; z=+q; // x- pnt.dat[i+0]=(x1+x); pnt.dat[i+1]=(y1+y); pnt.dat[i+2]=(z1-z); } for (z1-=2.0*a,i=m;i>=3;) { i--; z=pnt.dat[i]-z0; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; q=z; z=+x; x=-q; // y+ q=y; y=+z; z=-q; // x+ pnt.add(x1-x); pnt.add(y1+y); pnt.add(z1+z); } for (x1+=2.0*a,i=m;i>=3;) { i--; z=pnt.dat[i]-z0; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; q=y; y=+z; z=-q; // x+ pnt.add(x1+x); pnt.add(y1+y); pnt.add(z1+z); } for (z1+=2.0*a,i=m;i>=3;) { i--; z=pnt.dat[i]-z0; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; q=z; z=+x; x=-q; // y+ pnt.add(x1-x); pnt.add(y1-y); pnt.add(z1+z); } // mirror octants x0+=a; y0+=a; z0-=a; m=pnt.num; for (i=m;i>=3;) { i--; z=pnt.dat[i]-z0; i--; y=pnt.dat[i]-y0; i--; x=pnt.dat[i]-x0; pnt.add(x0+x); pnt.add(y0-y); pnt.add(z0+z); } a*=2.0; } /* // rotations q=z; z=+x; x=-q; // y+ q=z; z=-x; x=+q; // y- q=y; y=+z; z=-q; // x+ q=y; y=-z; z=+q; // x- q=x; x=+y; y=-q; // z+ q=x; x=-y; y=+q; // z- */ } //--------------------------------------------------------------------------- void pnt_draw2(List<double> &pnt) // piecewise linear { int i; glBegin(GL_LINE_STRIP); for (i=0;i<pnt.num;i+=3) glVertex3dv(pnt.dat+i); glEnd(); } //--------------------------------------------------------------------------- void pnt_draw4(List<double> &pnt) // piecewise cubic { int i,j; double d1,d2,t,tt,ttt,*p0,*p1,*p2,*p3,a0[3],a1[3],a2[3],a3[3],p[3]; glBegin(GL_LINE_STRIP); for (i=-3;i<pnt.num;i+=3) { j=i-3; if (j>pnt.num-3) j=pnt.num-3; if (j<0) j=0; p0=pnt.dat+j; j=i ; if (j>pnt.num-3) j=pnt.num-3; if (j<0) j=0; p1=pnt.dat+j; j=i+3; if (j>pnt.num-3) j=pnt.num-3; if (j<0) j=0; p2=pnt.dat+j; j=i+6; if (j>pnt.num-3) j=pnt.num-3; if (j<0) j=0; p3=pnt.dat+j; for (j=0;j<3;j++) { d1=0.5*(p2[j]-p0[j]); d2=0.5*(p3[j]-p1[j]); a0[j]=p1[j]; a1[j]=d1; a2[j]=(3.0*(p2[j]-p1[j]))-(2.0*d1)-d2; a3[j]=d1+d2+(2.0*(-p2[j]+p1[j])); } for (t=0.0;t<=1.0;t+=0.1) // single curve patch/segment { tt=t*t; ttt=tt*t; for (j=0;j<3;j++) p[j]=a0[j]+(a1[j]*t)+(a2[j]*tt)+(a3[j]*ttt); glVertex3dv(p); } } glEnd(); } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- List<double> xxx;相同
double xxx[];xxx.add(5);添加到列表的末尾
5访问数组元素(安全)
xxx[7]访问数组元素(不安全但快速直接访问)
xxx.dat[7]是数组的实际使用大小
xxx.num清除数组并设置xxx.reset()
xxx.num=0xxx.allocate(100)项目预分配空间

但您可以使用动态甚至静态 1D 数组,因为希尔伯特曲线的点数很容易计算(100在每个数字的开头希尔伯特函数)。

使用很简单就是这样做:

m

其中List<double> pnt; Hilbert3D(pnt,-0.8,-0.8,+0.8,1.6,n); 是迭代次数,n是每个点的pnt坐标的线性列表(每个点3个数字)。开始位置和初始大小设置为覆盖以(x,y,z)为中心的多维数据集,其大小为(0,0,0) 0.8

现在只计算点之间的单位长度,最左边的Hilbert曲线指向左边的索引和距离刚刚线性插值的参数(到它的距离)。这里 C ++ 示例:

<-0.8,+0.8>

2D预览:

2D

3D预览:

3D