Skip to content

Commit 2a83322

Browse files
committed
edit demos
1 parent 51ef1b9 commit 2a83322

File tree

4 files changed

+174
-82
lines changed

4 files changed

+174
-82
lines changed

demos/curves.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@
160160
var shapeGroup=new ShapeGroup();
161161
var allsettings={}
162162
var link0=null;
163+
164+
163165
addLink("Torus knot",link0=function(){
164166
pushSettings(function(allsettings){
165167
return makeMesh(

demos/extras.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ _FrenetFrames.prototype.getSampleAndBasisVectors=function(u){
173173
* @param {Object} [sweptCurve] Object describing
174174
* a curve to serve as the cross section of the extruded shape,
175175
* corresponding to the V coordinate of the ExtrudedTube's
176-
* "evaluate" method. If this parameter is null or omitted, uses a circular cross section <code>(sin(u),
177-
* cos(u), 0)</code> in which the V coordinate ranges from 0 through
176+
* "evaluate" method. If this parameter is null or omitted, uses a circular cross section
177+
* in which the V coordinate ranges from 0 through
178178
* 1. The curve object must contain a function
179179
* named "evaluate", with the same meaning as for the "func" parameter.<p>
180180
* The cross section will generally have a radius of 1 unit; bigger

demos/surfaces.html

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,25 @@
9191
var r=Math.cos(x);
9292
return Math.sign(r)*Math.pow(Math.abs(r),n);
9393
}
94+
9495
/**
95-
*
96-
*
97-
* @param {Function} phi Function of a single variable:
98-
* y = f(x). This determines the "radius" of the surface
99-
* of revolution along the y-axis.
100-
* @param {Function} psi Function of a single variable
101-
* that transforms the value x: x = f(a). If null, uses
102-
* the function x = f(a) = x.
103-
*
96+
* Parametric evaluator for a surface of revolution, which results by revolving
97+
* an X/Y curve around an axis.
98+
* @class
99+
* @alias SurfaceOfRevolution
100+
* @param {Function} curve Curve to rotate about the X-axis.
101+
* The curve function must contain a function
102+
* named "evaluate", which takes the following parameter:<ul>
103+
* <li><code>u</code> - A curve coordinate, generally from 0 to 1.
104+
* </ul>
105+
* The evaluator function returns an array of at least 2 elements: the first
106+
* element is the X coordinate of the curve's position, and the second
107+
* element is the Y coordinate.
108+
* @param {number} minval Smallest U-coordinate.
109+
* @param {number} maxval Largest U-coordinate.
104110
*/
105-
var SurfaceOfRevolution=function(phi,psi,minval,maxval){
106-
this.phi=phi;
107-
this.psi=psi;
111+
var SurfaceOfRevolution=function(curve,minval,maxval){
112+
this.curve=curve
108113
this.minval=minval
109114
this.maxval=maxval
110115
this.evaluate=function(u,v){
@@ -113,26 +118,60 @@
113118
u=minval+(maxval-minval)*u;
114119
var cosv = Math.cos(v);
115120
var sinv = (v>=0 && v<6.283185307179586) ? (v<=3.141592653589793 ? Math.sqrt(1.0-cosv*cosv) : -Math.sqrt(1.0-cosv*cosv)) : Math.sin(v);
116-
var r=this.phi(u);
117-
return [this.psi ? this.psi(u) : u,r*cosv,r*sinv];
121+
var curvepos=this.curve.evaluate(u);
122+
return [curvepos[0],curvepos[1]*cosv,curvepos[1]*sinv];
118123
}
119124
}
120-
121-
var FunctionSurface={
122-
create:function(func,minval,maxval){
123-
return new SurfaceOfRevolution(func,null,minval,maxval);
125+
/**
126+
* Parametric evaluator for a surface of revolution whose curve is the graph of
127+
* a single-variable function.
128+
* @param {Function} func Function whose graph will be
129+
* rotated about the X-axis. The function takes a number
130+
* as a single parameter and returns a number.
131+
* @param {number} minval Smallest parameter of the function.
132+
* @param {number} maxval Largest parameter of the function.
133+
* @return {SurfaceOfRevolution}
134+
*/
135+
SurfaceOfRevolution.fromFunction=function(func,minval,maxval){
136+
return new SurfaceOfRevolution({
137+
"evaluate":function(u){
138+
return [u,func(u),0];
139+
}},minval,maxval);
124140
}
125-
};
126-
127-
var Torus={
128-
create:function(outerRadius,innerRadius,minval,maxval){
129-
return new SurfaceOfRevolution(function(v){
130-
return outerRadius+innerRadius*Math.cos(v);
131-
},function(v){
132-
return innerRadius+Math.sin(v);
133-
},minval,maxval);
141+
/**
142+
* Parametric evaluator for a torus, a special case of a surface of revolution.
143+
* @param {number} outerRadius Radius from the center to the innermost
144+
* part of the torus.
145+
* @param {number} innerRadius Radius from the inner edge to the innermost
146+
* part of the torus.
147+
* @param {Function|undefined} curve Object describing
148+
* a curve to serve as the cross section of the torus.
149+
* The curve need not be closed; in fact, certain special surfaces can result
150+
* by leaving the ends open.
151+
* The curve function must contain a function
152+
* named "evaluate", which takes the following parameter:<ul>
153+
* <li><code>u</code> - A curve coordinate, generally from 0 to 1.
154+
* </ul>
155+
* The evaluator function returns an array of at least 2 elements: the first
156+
* element is the X coordinate of the curve's position, and the second
157+
* element is the Y coordinate. If null or omitted, uses a circular cross section.
158+
* @return {SurfaceOfRevolution}
159+
*/
160+
SurfaceOfRevolution.torus=function(outerRadius,innerRadius,curve){
161+
if(!curve)curve={
162+
"evaluate":function(u){
163+
u*=GLMath.PiTimes2;
164+
return [Math.sin(u),Math.cos(v)]
165+
}
166+
}
167+
return new SurfaceOfRevolution({
168+
"evaluate":function(u){
169+
var curvept=curve.evaluate(u)
170+
var x=innerRadius*curvept[1];
171+
var y=outerRadius+innerRadius*curvept[0];
172+
return [x,y,0];
173+
}},0,GLMath.PiTimes2);
134174
}
135-
};
136175

137176
var KleinBottle=function(){
138177
this.evaluate=function(u,v){
@@ -261,15 +300,15 @@
261300
})
262301
addLink("Surface of revolution for f(x) = sin x",function(){
263302
pushSettings(function(allsettings){
264-
return makeMesh(FunctionSurface.create(function(x){
303+
return makeMesh(SurfaceOfRevolution.fromFunction(function(x){
265304
return Math.sin(x)
266305
},-Math.PI,Math.PI))
267306
},{
268307
});
269308
})
270309
addLink("Surface of revolution for f(x) = x<sup>2</sup>",function(){
271310
pushSettings(function(allsettings){
272-
return makeMesh(FunctionSurface.create(function(x){
311+
return makeMesh(SurfaceOfRevolution.fromFunction(function(x){
273312
return x*x
274313
},-1,1))
275314
},{

demos/surfaces2d.html

Lines changed: 101 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -95,32 +95,25 @@
9595
var r=Math.cos(x);
9696
return Math.sign(r)*Math.pow(Math.abs(r),n);
9797
}
98-
var RevolutionSurface=function(func,minval,maxval){
99-
this.func=func
100-
this.minval=minval
101-
this.maxval=maxval
102-
this.evaluate=function(u,v){
103-
v=1-v;
104-
v*=GLMath.PiTimes2;
105-
u=minval+(maxval-minval)*u;
106-
var r=this.func(u);
107-
return [u,r*Math.cos(v),r*Math.sin(v)];
108-
}
109-
}
98+
11099
/**
111-
*
112-
*
113-
* @param {Function} phi Function of a single variable:
114-
* y = f(x). This determines the "radius" of the surface
115-
* of revolution along the y-axis.
116-
* @param {Function} psi Function of a single variable
117-
* that transforms the value x: x = f(a). If null, uses
118-
* the function x = f(a) = x.
119-
*
100+
* Parametric evaluator for a surface of revolution, which results by revolving
101+
* an X/Y curve around an axis.
102+
* @class
103+
* @alias SurfaceOfRevolution
104+
* @param {Function} curve Curve to rotate about the X-axis.
105+
* The curve function must contain a function
106+
* named "evaluate", which takes the following parameter:<ul>
107+
* <li><code>u</code> - A curve coordinate, generally from 0 to 1.
108+
* </ul>
109+
* The evaluator function returns an array of at least 2 elements: the first
110+
* element is the X coordinate of the curve's position, and the second
111+
* element is the Y coordinate.
112+
* @param {number} minval Smallest U-coordinate.
113+
* @param {number} maxval Largest U-coordinate.
120114
*/
121-
var SurfaceOfRevolution=function(phi,psi,minval,maxval){
122-
this.phi=phi;
123-
this.psi=psi;
115+
var SurfaceOfRevolution=function(curve,minval,maxval){
116+
this.curve=curve
124117
this.minval=minval
125118
this.maxval=maxval
126119
this.evaluate=function(u,v){
@@ -129,37 +122,71 @@
129122
u=minval+(maxval-minval)*u;
130123
var cosv = Math.cos(v);
131124
var sinv = (v>=0 && v<6.283185307179586) ? (v<=3.141592653589793 ? Math.sqrt(1.0-cosv*cosv) : -Math.sqrt(1.0-cosv*cosv)) : Math.sin(v);
132-
var r=this.phi(u);
133-
return [this.psi ? this.psi(u) : u,r*cosv,r*sinv];
125+
var curvepos=this.curve.evaluate(u);
126+
return [curvepos[0],curvepos[1]*cosv,curvepos[1]*sinv];
134127
}
135128
}
136-
137-
var FunctionSurface={
138-
create:function(func,minval,maxval){
139-
return new SurfaceOfRevolution(func,null,minval,maxval);
129+
/**
130+
* Parametric evaluator for a surface of revolution whose curve is the graph of
131+
* a single-variable function.
132+
* @param {Function} func Function whose graph will be
133+
* rotated about the X-axis. The function takes a number
134+
* as a single parameter and returns a number.
135+
* @param {number} minval Smallest parameter of the function.
136+
* @param {number} maxval Largest parameter of the function.
137+
* @return {SurfaceOfRevolution}
138+
*/
139+
SurfaceOfRevolution.fromFunction=function(func,minval,maxval){
140+
return new SurfaceOfRevolution({
141+
"evaluate":function(u){
142+
return [u,func(u),0];
143+
}},minval,maxval);
140144
}
141-
};
142-
143-
var Torus={
144-
create:function(outerRadius,innerRadius,minval,maxval){
145-
return new SurfaceOfRevolution(function(v){
146-
return outerRadius+innerRadius*Math.cos(v);
147-
},function(v){
148-
return innerRadius+Math.sin(v);
149-
},minval,maxval);
145+
/**
146+
* Parametric evaluator for a torus, a special case of a surface of revolution.
147+
* @param {number} outerRadius Radius from the center to the innermost
148+
* part of the torus.
149+
* @param {number} innerRadius Radius from the inner edge to the innermost
150+
* part of the torus.
151+
* @param {Function|undefined} curve Object describing
152+
* a curve to serve as the cross section of the torus.
153+
* The curve need not be closed; in fact, certain special surfaces can result
154+
* by leaving the ends open.
155+
* The curve function must contain a function
156+
* named "evaluate", which takes the following parameter:<ul>
157+
* <li><code>u</code> - A curve coordinate, generally from 0 to 1.
158+
* </ul>
159+
* The evaluator function returns an array of at least 2 elements: the first
160+
* element is the X coordinate of the curve's position, and the second
161+
* element is the Y coordinate. If null or omitted, uses a circular cross section.
162+
* @return {SurfaceOfRevolution}
163+
*/
164+
SurfaceOfRevolution.torus=function(outerRadius,innerRadius,curve){
165+
if(!curve)curve={
166+
"evaluate":function(u){
167+
u*=GLMath.PiTimes2;
168+
return [Math.sin(u),Math.cos(v)]
169+
}
170+
}
171+
return new SurfaceOfRevolution({
172+
"evaluate":function(u){
173+
var curvept=curve.evaluate(u)
174+
var x=innerRadius*curvept[1];
175+
var y=outerRadius+innerRadius*curvept[0];
176+
return [x,y,0];
177+
}},0,GLMath.PiTimes2);
150178
}
151-
};
152179

153180
var KleinBottle=function(){
154181
this.evaluate=function(u,v){
155182
var cospi;
156183
u*=GLMath.PiTimes2;
157184
v*=GLMath.PiTimes2;
158185
var x, y, z;
159-
var sinu=Math.sin(u);
160-
var sinv=Math.sin(v);
161-
var cosu=Math.cos(u);
162-
var cosv=Math.cos(v);
186+
var cosu = Math.cos(u);
187+
var sinu = (u>=0 && u<6.283185307179586) ? (u<=3.141592653589793 ? Math.sqrt(1.0-cosu*cosu) : -Math.sqrt(1.0-cosu*cosu)) : Math.sin(u);
188+
var cosv = Math.cos(v);
189+
var sinv = (v>=0 && v<6.283185307179586) ? (v<=3.141592653589793 ? Math.sqrt(1.0-cosv*cosv) : -Math.sqrt(1.0-cosv*cosv)) : Math.sin(v);
163190
if(u<Math.PI){
164191
x = 3 * cosu * (1 + sinu) + (2 * (1 - cosu / 2)) * cosu * cosv;
165192
z = -8 * sinu - 2 * (1 - cosu / 2) * sinu * cosv;
@@ -277,15 +304,15 @@
277304
})
278305
addLink("Surface of revolution for f(x) = sin x",function(){
279306
pushSettings(function(allsettings){
280-
return makeMesh(FunctionSurface.create(function(x){
307+
return makeMesh(SurfaceOfRevolution.fromFunction(function(x){
281308
return Math.sin(x)
282309
},-Math.PI,Math.PI))
283310
},{
284311
});
285312
})
286313
addLink("Surface of revolution for f(x) = x<sup>2</sup>",function(){
287314
pushSettings(function(allsettings){
288-
return makeMesh(FunctionSurface.create(function(x){
315+
return makeMesh(SurfaceOfRevolution.fromFunction(function(x){
289316
return x*x
290317
},-1,1))
291318
},{
@@ -295,10 +322,11 @@
295322
addLink("M&ouml;bius-like strip",function(){
296323
pushSettings(function(allsettings){
297324
return makeMesh(
298-
new ExtrudedTube(new TorusKnot(
299-
allsettings["torusknot-p"],
300-
allsettings["torusknot-q"]
301-
),0.1,TorusKnot.getFlatCurve(5)),100);
325+
new MoebiusLikeStrip(
326+
allsettings["moeb-maj"],
327+
allsettings["moeb-a"],
328+
allsettings["moeb-b"]
329+
));
302330
},{
303331
"moeb-maj":["Size",1.25,0.05,3.0,0.05],
304332
"moeb-a":["Height",0.125,0.05,2.0,0.05],
@@ -337,6 +365,29 @@
337365
"moeb2-w":["Width",0.25,0.05,2,0.05]
338366
});
339367
});
368+
369+
var bsplineSurf=null;
370+
addLink("B-Spline Surface",function(){
371+
pushSettings(function(allsettings){
372+
var bspline=[]
373+
for(var i=0;i<=5;i++){
374+
var c=[]
375+
for(var j=0;j<=5;j++){
376+
var cp=[
377+
(j*5.0/5)-2.5,
378+
(i*5.0/5)-2.5,
379+
Math.random()*2.5-1.25
380+
]
381+
c.push(cp)
382+
}
383+
bspline.push(c)
384+
}
385+
if(!bsplineSurf)
386+
bsplineSurf=BSplineSurface.clamped(bspline,3,3)
387+
return makeMesh(bsplineSurf);
388+
},{
389+
});
390+
})
340391
// Create the 3D scene; find the HTML canvas and pass it
341392
// to Scene3D.
342393
var scene=new Scene3D(document.getElementById("canvas"));

0 commit comments

Comments
 (0)