File: bezier.e

package info (click to toggle)
euler 1.61.0-12
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 5,164 kB
  • sloc: ansic: 24,761; sh: 8,314; makefile: 141; cpp: 47; php: 1
file content (195 lines) | stat: -rw-r--r-- 4,929 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
comment
Compute Bezier curves.
For a test try:
beziertest; bezier3dtest; nurbstest; beziersurftest; c1test;
Uses the following functions:
bezier, bezier3d, nurbs, beziersurface
endcomment

reset();

function bezier (p,t)
## Evaluate sum p_i B_{i,n}(t) the easy and direct way.
## p must be a k x n+1 matrix (n+1) points, dimension k.
	n=cols(p)-1; i=nonzeros(t~=1);
	if cols(i)>0; t[i]=0.9999*ones(size(i)); endif;
	T=dup(t/(1-t),n)';
	b=((1-t')^n)|(T*dup((n-(1:n)+1)/(1:n),cols(t)));
	b=cumprod(b);
	if (cols(i)>0); b[i]=zeros(1,n)|1; endif;
	return p.b';
endfunction

function bezier2 (p,t)
## Evaluate sum p_i B_{i,n}(t) the complicated way.
## p_i is a k x n+1 matrix (n+1) points, dimension k.
	n=cols(p)-1;
	{T,N}=field(t,0:n);
	b=bin(n,N)*T^N*(1-T)^(n-N);
	return p.b;
endfunction

function gammatest (N=[10,20,50,100])
## Bezier curve approximating a circle
	x=linspace(0,1,100);
	linewidth(4); xplot(cos(2*pi*x),sin(2*pi*x)); linewidth(1);
	loop 1 to cols(N);
	n=N[#];
	t=sqrt(linspace(0,1,n));
	p=cos(2*pi*t)_sin(2*pi*t);
	y=bezier(p,x);
	hold on; plot(y[1],y[2]); hold off;
	end;
	return "";
endfunction

function gammatest1 (N=[10,20,50,100])
## Bezier curve approximating a circle
	x=linspace(0,1,100);
	linewidth(4); xplot(cos(2*pi*x),sin(2*pi*x)); linewidth(1);
	loop 1 to cols(N);
	n=N[#];
	t=linspace(0,1,n);
	p=cos(2*pi*t)_sin(2*pi*t);
	y=bezier(p,x);
	hold on; plot(y[1],y[2]); hold off;
	end;
	return "";
endfunction

function beziertest
## The user clicks some points, which form the Bezier polygon.
## The program draws the Bezier curve
	setplot(-1,1,-1,1);
	xplot(-1,1); hold on;
	p=zeros(2,0);
	title("Mark points (click here for end)");
	repeat
		m=mouse();
		if (cols(p)>0) && (m[2]>1); break; endif;
		p=p|m';
		plot(p[1],p[2]);
	end;
	t=linspace(0,1,300);
	s=bezier(p,t);
	color(2); plot(s[1],s[2]);
	hold off;
	return "";
endfunction

function bezier3d (p)
## Shows a 3D Bezier curve and its polygon
	t=linspace(0,1,300);
	s=bezier(p,t);
	f=getframe(p[1],p[2],p[3]);
	h=holding(1); if !h; clg; endif;
	co=color(2); frame1(f);
	color(1); wire(p[1],p[2],p[3]);
	color(3); wire(s[1],s[2],s[3]);
	color(2); frame2(f);
	color(co);
	holding(h);
	return "";
endfunction	

function bezier3dtest (alpha=0.5,beta=0.5)
## Show a Beziercurve of dimension 3
	p=[-1,-1,-1;0,-1,-1;1,0,0;1,1,0;0,1,1;-1,1,0]';
	view(3,1.5,alpha,beta);
	bezier3d(p);
	return "";
endfunction

function nurbs (p,b,t)
## Cumpute a rational Bezier curve with control points p
## and weights b.
	K=rows(p);
	pp=(p*dup(b,K))_b;
	s=bezier(pp,t);
	return s[1:K]/(dup(s[K+1],K));
endfunction

function nurbstest
## Show some NURBS.
	p=[-1,0;0,1;1,0]';
	b=[1,1,1];
	bb=2^(-5:5);
	setplot(-1,1,0,2); clg; frame(); xplot();
	hold on; linewidth(2); plot(p[1],p[2]); linewidth(1); hold off;
	t=linspace(0,1,300);
	loop 1 to cols(bb);
		b[2]=bb[#];
		s=nurbs(p,b,t);
		hold on; plot(s[1],s[2]); hold off;
	end;
	return title("Quadratic NURBS");
endfunction

function beziersurface (x,y,z,n=20)
## Compute a Bezier surface. Return {bx,by,bz}.
	t=linspace(0,0.99999,n);
	n=rows(x)-1; i=nonzeros(t~=1);
	T=dup(t/(1-t),n)';
	b1=((1-t')^n)|(T*dup((n-(1:n)+1)/(1:n),cols(t)));
	b1=cumprod(b1);
	if (cols(i)>0); b1[i]=zeros(1,n)|1; endif;
	n=cols(x)-1; i=nonzeros(t~=1);
	T=dup(t/(1-t),n)';
	b2=((1-t')^n)|(T*dup((n-(1:n)+1)/(1:n),cols(t)));
	b2=cumprod(b2);
	if (cols(i)>0); b2[i]=zeros(1,n)|1; endif;
	return {b1.x.b2',b1.y.b2',b1.z.b2'};
endfunction

function beziersurftest
## Show a Bezier surface
	{x,y}=field(-1:0.5:1,-1:0.5:1);
	z=2*exp(-(0.5*x*x+y*y))-1;
	view(2.5,1.5,0.5,0.5);
	{xb,yb,zb}=beziersurface(x,y,z);
	wi=wirecolor(1); linewidth(3);
	wire(x[3:5,1:5],y[3:5,1:5],z[3:5,1:5]); hold on;
	linewidth(1); wirecolor(wi);
	solid(xb,yb,zb);
	wi=wirecolor(1); linewidth(3);
	wire(x[1:3,1:5],y[1:3,1:5],z[1:3,1:5]); hold on;
	linewidth(1); wirecolor(wi);
	hold off;
	return title("A Bezier surface");
endfunction

function c1test
## Show how two bezier surfaces can be joined.
	x1=dup(-0.5:0.25:0.5,5);
	y1=dup([0,0,0,0,1],5);
	z1=dup(1:0.25:2,5)';
	{xb1,yb1,zb1}=beziersurface(x1,y1,z1,10);
	x2=dup(-0.5:0.25:0.5,5);
	y2=(-ones(4,5))_[0,0,0,0,0];
	z2=dup(-1:0.25:0,5)';
	{xb2,yb2,zb2}=beziersurface(x2,y2,z2,10);
	x=zeros(5,5); y=x; z=x;
	x[1]=x1[1]; x[2]=x[1]-(x1[2]-x1[1]);
	x[5]=x2[5]; x[4]=x[5]+(x2[5]-x2[4]);
	x[3]=(x[4]+x[2])/2;
	y[1]=y1[1]; y[2]=y[1]-(y1[2]-y1[1]);
	y[5]=y2[5]; y[4]=y[5]+(y2[5]-y2[4]);
	y[3]=(y[4]+y[2])/2;
	z[1]=z1[1]; z[2]=z[1]-(z1[2]-z1[1]);
	z[5]=z2[5]; z[4]=z[5]+(z2[5]-z2[4]);
	z[3]=(z[4]+z[2])/2;
	{xb,yb,zb}=beziersurface(x,y,z,10);
	view(4,2,0.5,0.5);
	solid(xb1,yb1,zb1-1); hold on;
	solid(xb,yb,zb-1); solid(xb2,yb2,zb2-1);
	hold off;
	title("C1 continuity of Bezier surfaces");
	wait(180);
	wi=wirecolor(1);
	linewidth(1); wire(x,y,z-1); linewidth(3);
	hold on; wire(x1,y1,z1-1); wire(x2,y2,z2-1); hold off;
	wirecolor(wi); linewidth(1);
	return title("C1 continuity of the Bezier grid");
endfunction

.. EOF