Published
Edited
Oct 19, 2021
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
gl.canvas
Insert cell
Insert cell
Insert cell
render = {
gl.regl.frame(({ tick }) => {
camera.tick();
// const time = (tick / 2) % 100;
// gl.regl.clear({
// color: [0, 0, 0, 0],
// depth: 1,
// stencil: 0
// })
if(content0 && content1){
draw();
}

});
}
Insert cell
bspline1.length
Insert cell
function draw() {
const view = camera.view();
// drawGrid({ view });
const surface = [];
// const step = 1 / steps;
for (let u = 0; u < bspline1.length; u ++) {
for (let v = 0; v < bspline2.length; v ++) {
// const c = bezier_surface(curvePoints, [u, v]);
const tmp = bsplineSurfaceSweep(bspline2, bspline1, [u, v])
surface.push(tmp);
}
}
for (let i = 0; i < steps; ++i) {
const color = [0.2, 0.2, 1, 0.8];
drawCurve({
view,
count: steps,
point: surface.slice(i * steps, i * steps + steps + 1),
color
});
drawCurve({
view,
count: steps,
point: surface.filter((v, j) => j % steps === i),
color
});
}
// console.log(surface.length)
if((surface.length > 1 && !mutable drawOnce) || (rotateDegree != mutable outputDegreeTracker)){
mutable drawOnce = true
mutable outputDegreeTracker = rotateDegree
outputString(surface)
}
}
Insert cell
outputDegreeTracker
Insert cell
mutable drawOnce = false
Insert cell
mutable outputDegreeTracker = 0
Insert cell
mutable rotateDegreeTracker = 0
Insert cell
rotateDegreeAdd = {
if(rotateDegree != rotateDegreeTracker){
mutable rotateDegreeTracker = rotateDegree
// mutable gl = createGL();
for(let i=0; i<bspline1.length; i++){
bspline1[i] = [
cosine(rotateDegreeTracker)*bspline1[i][0] + sine(rotateDegreeTracker)*bspline1[i][1],
-sine(rotateDegreeTracker)*bspline1[i][0] + cosine(rotateDegreeTracker)*bspline1[i][1],
bspline1[i][2]
]
}
}
}
Insert cell
function cosine(degree){
return Math.cos((degree/180) * Math.PI)
}
Insert cell
function sine(degree){
return Math.sin((degree/180) * Math.PI)
}
Insert cell
function bsplineSurfaceSweep(sweepLine, refLine, [u, v]){
let cur = sweepLine[u]
let ref = refLine[v]
let orig = refLine[0]
return [
cur[0] + ref[0] - orig[0],
cur[1] + ref[1] - orig[1],
cur[2] + ref[2] - orig[2]
]
}
Insert cell
function bsplineBasis(i,k,knots)
{
if(k==1)
{
return (function(t) { if((knots[i]<=t) && (t<knots[i+1])) {return 1;} else {return 0;}});
}
else
{
return (function(t) {
if(bsplineBasis(i,k-1,knots)(t) == 0){
if(bsplineBasis(i+1,k-1, knots)(t) == 0){
return 0;
}else{
return bsplineBasis(i+1,k-1,knots)(t)*(knots[i+k]-t)/(knots[i+k]-knots[i+1]);
}
}else if(bsplineBasis(i+1,k-1,knots)(t)*( knots[i+k]-t) == 0){
if(bsplineBasis(i,k-1,knots)(t) == 0){
return 0;
}else{
return bsplineBasis(i,k-1,knots)(t)*(t- knots[i])/(knots[i+k-1]- knots[i]);
}
}
else {
return bsplineBasis(i,k-1,knots)(t)*(t- knots[i])/( knots[i+k-1]- knots[i]) + bsplineBasis(i+1,k-1,knots)(t)*( knots[i+k]-t)/( knots[i+k]- knots[i+1]);
}
})
}
}

Insert cell
function bspline(t, knots, points, numDegree, numPoints)
{
let i=numDegree;
while(knots[i+1]<=t)
{
i=i+1;
}
if(i>numPoints-1) i=numPoints-1;
var x=0;
var y=0;
for(let j = numDegree; j >= 0; j--){
x += bsplineBasis(i-j,numDegree+1, knots)(t)*(points)[i-j][0]
y += bsplineBasis(i-j,numDegree+1, knots)(t)*(points)[i-j][1]
}
return [x, y];
}
Insert cell
function makeCurve(points, knots, numDegree, steps) {
const numP = points.length
if(numP < 2){
return [[0,0]]
}
const curve = d3.range(steps).map(function(i) { return bspline((knots)[numDegree]+((knots)[numP]- (knots)[numDegree])*i/steps, knots, points, numDegree, numP);})
return curve;
}
Insert cell
drawCurve = gl.regl({
vert: `
precision mediump float;
attribute vec3 point;
uniform mat4 proj;
uniform mat4 view;
void main () {
gl_Position = proj * view * vec4(point, 1.0);
}
`,
frag: `
precision mediump float;

uniform bool highlight;
uniform vec4 color;

void main () {
gl_FragColor = color;
}
`,
attributes: {
point: gl.regl.prop('point')
},
uniforms: {
view: gl.regl.prop('view'),
proj: mat4.perspective([], Math.PI / 4, width / height, 0.001, 10000),
highlight: gl.regl.prop('highlight'),
color: gl.regl.prop('color')
},
count: gl.regl.prop('count'),
primitive: 'line strip'
})
Insert cell
fileInputTracker0 = {
let obj = {
"name": "",
"lastModifiedDate": ""
}
return obj
}
Insert cell
fileInputTracker1 = {
let obj = {
"name": "",
"lastModifiedDate": ""
}
return obj
}
Insert cell
dataLoadIn = {
if(content0
&& content1
&& (file0.name != fileInputTracker0.name || file0.lastModified.toString() != fileInputTracker0.lastModifiedDate || file1.name != fileInputTracker1.name || file1.lastModified.toString() != fileInputTracker1.lastModifiedDate)){
fileInputTracker0.name = file0.name
fileInputTracker0.lastModifiedDate = file0.lastModified.toString()
fileInputTracker1.name = file1.name
fileInputTracker1.lastModifiedDate = file1.lastModified.toString()
// mutable gl = createGL();
const obj0 = fileProcess(content0)
mutable numDegree_1 = obj0['meta'][2]
mutable points_1 = obj0['points']
mutable knots_1 = obj0['knots']
const obj1 = fileProcess(content1)
mutable numDegree_2 = obj1['meta'][2]
mutable points_2 = obj1['points']
mutable knots_2 = obj1['knots']
gl.regl.clear({
color: [0, 0, 0, 0],
depth: 1,
stencil: 0
})
draw()
}
}
Insert cell
function fileProcess(content){
let loadInData = content.trim().split("\n")
const filteredData = loadInData.filter(obj => {
if(obj.startsWith("BSPLINE")){
return false
}else if(obj.startsWith("#")){
return false
}else{
return true
}
})
let [dimension, numOfPoints, degree] = filteredData[0].trim().split(' ').map(i => parseInt(i))
let tmpKnots = filteredData[1].trim().split(' ').map(i => parseInt(i))
let dataPoints = []
filteredData.slice(2).forEach(obj => {
let tmpD = obj.trim().split(' ').map(i => parseFloat(i))
dataPoints.push([tmpD[0], tmpD[1]])
})
return {
'meta': [dimension, numOfPoints, degree],
'points': dataPoints,
'knots': tmpKnots
}
}
Insert cell
camera = {
const camera = createCamera(gl.canvas);
// camera.lookAt([bspline1[bspline1.length/2][0], bspline1[bspline1.length/2][1], bspline1[bspline1.length/2][2]], [0, 0, 0], [0, 1, 0]);
// camera.lookAt([1, 0, 0], [0, 0, 1], [0, 1, 0]);
camera.lookAt([0, 2, -2], [0, 0, 1], [0, 1, 0]);
return camera;
}
Insert cell
mutable gl = createGL();
Insert cell
function createGL(opts) {
var canvas = DOM.canvas(width, height)
var regl = createREGL(Object.assign({ canvas: canvas }, opts || {}));
return { canvas, regl };
}
Insert cell
height = width
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
bspline1
Insert cell
pointsDimensionAdd = {
if(bspline1.length > 0){
for(let i=0;i<bspline1.length; i++){
mutable bspline1[i] = [0, bspline1[i][0], bspline1[i][1]]
}
}
if(bspline2.length > 0){
for(let i=0;i<bspline2.length; i++){
mutable bspline2[i] = [bspline2[i][0], bspline2[i][1], 0]
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
mutable tp = []
Insert cell
function outputString(surface){
console.log("here")
let tmpStr = ``
tmpStr += "OFF\n"
// tmpStr += "" + surface.length + " " + (steps-1) * (steps-1) + " " + (steps-1)*steps+steps*(steps-1) +"\n"
tmpStr += "" + surface.length + " " + (steps-1) * (steps-1) + " " + 0 +"\n"
for(let i=0;i<surface.length;i++){
tmpStr += surface[i][0] + " " + surface[i][1] + " " + surface[i][2]+"\n"
}
let surfaceArr = []
for (let i = 0; i < steps; i++) {
let tmp = surface.slice(i * steps, i * steps + steps)
surfaceArr.push(tmp)
}
for(let i = 0; i < surfaceArr.length-1; i++){
for(let j = 0; j < surfaceArr[0].length-1; j++){
tmpStr += [4, i*steps + j, (i+1)*steps + j, (i+1)*steps + j + 1, i*steps + j + 1].join(" ") + "\n"
}
}
// if(tmpStr != output){
mutable output = tmpStr
// }
}
Insert cell
Insert cell
mat4 = require('https://bundle.run/gl-mat4@1.0.0')
Insert cell
createCamera = require("https://bundle.run/canvas-orbit-camera@1.0.2")
Insert cell
createREGL = require('https://unpkg.com/regl@1.3.1/dist/regl.min.js')
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more