Getting control points and knots on a NurbsSurface in Javascript

Hi there!

I am working on a proof of concept mixing rhino3dm.js, Three.js and Y.js to create a p2p collaborative Grasshopper-like application in the browser (you can play with two open browser windows to see them interact): Link to prototype

The way I reconstruct Breps in Three.js at the moment is by getting the points of each face and making a ConvexGeometry with the point cloud:

export function faceToPoints(face) {
  const points = [];
  const loops = 20;
  face.setDomain(0, [0, 1]);
  face.setDomain(1, [0, 1]);
  for (let u = 0; u <= loops; u++) {
    for (let v = 0; v <= loops; v++) {
      const point = face.pointAt(u / loops, v / loops);
      points.push(new THREE.Vector3(point[0], point[1], point[2]));
  return points;

Right now the NurbsSuface instance in rhino3dm.js is missing some of the methods available in the python library, like getting the control points, knots etc.

I noticed that Threejs has support for NURBS surfaces. And so being able to get the control points would hopefully make it easier to convert faces of a Brep to a Threejs representation, instead of the manual way I’m doing it now.

Until then, does anyone know better ways to reconstruct a surface based on points on a surface in Three.js? I was trying with the delunator, but it only really works in 2d, or a 3d surface that does not “wrap” over itself. I have looked into the Ball Pivot algorithm, but couldn’t find any wasm port or javascript implementation. Also I have no previous experience in this 3D stuff, so I feel a bit stuck at this point.

@fraguada - is this something you know about?

I’ve recently exposed points for NurbsSurfaces in js.

You would do something like this:


//assuming object is a Brep
const nurbsSurface = object.geometry().surfaces().get( 0 ).toNurbsSurface()

const points = []

const cnt_u = nurbsSurface.points().countU
const cnt_v = nurbsSurface.points().countV

for ( let u = 0; u < cnt_u; u ++ ) {

    for ( let v = 0; v < cnt_v; v ++ ) {

        // const pt4d = nurbssurface.points().get( u, v ) //this returns a ON_4dPoint which is [x,y,z,w] 
        // to get the 3d version, you can do [ x/w, y/w, z/w ]
        // or use the following new method:

        const pt3d = nurbssurface.points().getPoint( u, v ) // this returns a ON_3dPoint

        const pt = new THREE.Vector3().fromArray( pt3d )
        points.push( pt )


const cp_geometry = new THREE.BufferGeometry().setFromPoints( points )
const cp_material = new THREE.PointsMaterial( { color: 0xff0000, size: 5, sizeAttenuation: false } )
const cps = new THREE.Points( cp_geometry, cp_material )
scene.add( cps )


Working on a sample to show all of this. Red pts are control points, black points are sampled off of the Surface ( object.geometry().surfaces().get( 0 ) ):

Original surface in Rhino:

I will work on a few other things before preparing the next release, but you can try it now (for the next 15 days) by using this version:

1 Like