Create A Nurbsurface

Create A Nurbsurface

john4TMYX
Enthusiast Enthusiast
407 Views
1 Reply
Message 1 of 2

Create A Nurbsurface

john4TMYX
Enthusiast
Enthusiast

Hi guys,

 

I have searched this board, there is a message in 2019 saying the function:

 

adsk::core::NurbsSurface::create

 

doesn't work. It is not possible to create a nurb surface. I have tried hard to create a nurb surface with this API, but it always fails. Just want to have a confirmation from AutoDesk experts whether this API indeed doesn't work or not. If it works, could you please give me an sample? a very simple sample codes will be good enough for me to continue. 

 

Please help!

Thank you very much.

 

Regards

John

0 Likes
Accepted solutions (1)
408 Views
1 Reply
Reply (1)
Message 2 of 2

BrianEkins
Mentor
Mentor
Accepted solution

It is possible to create a NURBS surface using the API. However, usually, having the NURBS surface isn't enough, and you want to create a face in Fusion whose shape is defined by that surface. Below is some code that does both. It asks you to select a planar face, checks that the face has four linear edges and then uses that information to create a bulged NURBS surface from that face. It then uses that NURBS definition to create a body that contains a single face and finally uses that to create a body in a base feature in the active design. Here's an example of what it creates where the top face on the body is selected, and the yellow face is the result.

BulgeExample.png

 

import adsk.core, adsk.fusion, traceback
from typing import Tuple

_app = adsk.core.Application.get()
_ui  = _app.userInterface


def run(context):
    try:
        face: adsk.fusion.BRepFace = _ui.selectEntity('Select planar face with four linear sides.', 'PlanarFaces').entity
        if face.edges.count != 4:
            _ui.messageBox('The selected face must have 4 linear sides.')
            return

        for edge in face.edges:
            if edge.geometry.objectType != adsk.core.Line3D.classType():
                _ui.messageBox('The selected face must have 4 linear sides.')
                return

        bulgeFace = buildBulgeSurfaceBody(face, 5)

        # Add the face to the model using a base feature.
        des: adsk.fusion.Design = _app.activeProduct
        root = des.rootComponent
        bf = root.features.baseFeatures.add()
        bf.startEdit()
        root.bRepBodies.add(bulgeFace[0], bf)
        bf.finishEdit()
    except:
        _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def buildBulgeSurfaceBody(face: adsk.fusion.BRepFace, bulgeDistance: float) -> adsk.fusion.BRepBody:
    try:       
        # Define a 3x3 control point surface that fits over the face where
        # the outer bounds follow the four lines and the middle control
        # point is at the center and offset by the bulge distance.
        loop : adsk.fusion.BRepLoop = face.loops.item(0)
        firstCoedge = loop.coEdges.item(0)
        oppositeCoedge = loop.coEdges.item(2)

        # Define the four corner points.  The others are midpoints of these.
        #         M4 E2
        #   2 +----+----+ 3
        #     |         |
        #  M1 +  M2+    + M3 
        #  E3 |         | E1
        #   0 +----+----+ 1       
        #         M0 E0
        #

        # Get the end points of the first edge.
        (pnt0, pnt1) = getCoedgeEndPoints(firstCoedge)
        mid0 = midPoint(pnt0, pnt1)

        # Get the end points of the opposite edge.
        (pnt3, pnt2) = getCoedgeEndPoints(oppositeCoedge)
        mid4 = midPoint(pnt2, pnt3)

        # Calculate the midline points.
        mid1 = midPoint(pnt0, pnt2)
        mid2 = midPoint(mid0, mid4)
        mid3 = midPoint(pnt1, pnt3)

        curve0ControlPoints = [pnt0, mid0, pnt1]        
        curve0 = adsk.core.NurbsCurve3D.createNonRational(curve0ControlPoints, 2, [0.0, 0.0, 0.0, 1.0, 1.0, 1.0], False)

        curve1ControlPoints = [pnt1, mid3, pnt3]        
        curve1 = adsk.core.NurbsCurve3D.createNonRational(curve1ControlPoints, 2, [0.0, 0.0, 0.0, 1.0, 1.0, 1.0], False)

        curve2ControlPoints = [pnt3, mid4, pnt2]        
        curve2 = adsk.core.NurbsCurve3D.createNonRational(curve2ControlPoints, 2, [0.0, 0.0, 0.0, 1.0, 1.0, 1.0], False)

        curve3ControlPoints = [pnt2, mid1, pnt0]        
        curve3 = adsk.core.NurbsCurve3D.createNonRational(curve3ControlPoints, 2, [0.0, 0.0, 0.0, 1.0, 1.0, 1.0], False)

        linePoint = mid2.copy()
        (_, normal) = face.evaluator.getNormalAtPoint(mid2)
        normal.scaleBy(bulgeDistance * 2)
        mid2.translateBy(normal)

        (_, normal) = face.evaluator.getNormalAtPoint(mid2)
        normal.scaleBy(bulgeDistance)
        linePoint.translateBy(normal)

        surfaceControlPoints = [pnt0, mid0, pnt1, mid1, mid2, mid3, pnt2, mid4, pnt3]

        surf = adsk.core.NurbsSurface.create(2, 2, 3, 3, surfaceControlPoints, 
                                            [0.0, 0.0, 0.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 1.0, 1.0, 1.0], 
                                            [], adsk.core.NurbsSurfaceProperties.OpenNurbsSurface, 
                                            adsk.core.NurbsSurfaceProperties.OpenNurbsSurface)

        bodyDef = adsk.fusion.BRepBodyDefinition.create()
        bodyDef.createVertexDefinition

        vertDefs = []
        vertDefs.append(bodyDef.createVertexDefinition(pnt0))
        vertDefs.append(bodyDef.createVertexDefinition(pnt1))
        vertDefs.append(bodyDef.createVertexDefinition(pnt2))
        vertDefs.append(bodyDef.createVertexDefinition(pnt3))

        edgeDefs = []
        edgeDefs.append(bodyDef.createEdgeDefinitionByCurve(vertDefs[0], vertDefs[1], curve0))
        edgeDefs.append(bodyDef.createEdgeDefinitionByCurve(vertDefs[1], vertDefs[2], curve1))
        edgeDefs.append(bodyDef.createEdgeDefinitionByCurve(vertDefs[2], vertDefs[3], curve2))
        edgeDefs.append(bodyDef.createEdgeDefinitionByCurve(vertDefs[3], vertDefs[0], curve3))

        lumpDef = bodyDef.lumpDefinitions.add()
        shellDef = lumpDef.shellDefinitions.add()
        faceDef = shellDef.faceDefinitions.add(surf, False)
        faceDef.associativeID = 1

        loopDef = faceDef.loopDefinitions.add()
        for edgeDef in edgeDefs:
            loopDef.bRepCoEdgeDefinitions.add(edgeDef, False)
        
        newBody = bodyDef.createBody()
        if not newBody:
            _ui.messageBox(bodyDef.outcomeInfo)

        points = [pnt0, pnt1, pnt2, pnt3, linePoint]
        return (newBody, points)           
    except:
        _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Return the coordinate that represents the midpoint of the two input points.
def midPoint(pnt1 : adsk.core.Point3D, pnt2 : adsk.core.Point3D) -> adsk.core.Point3D:
    return adsk.core.Point3D.create((pnt1.x + pnt2.x) / 2,
                                    (pnt1.y + pnt2.y) / 2,
                                    (pnt1.z + pnt2.z) / 2)


# Returns the vertices that correspond with the start and end points of a coedge.
def getCoedgeEndPoints(coEdge : adsk.fusion.BRepCoEdge) -> Tuple[adsk.core.Point3D, adsk.core.Point3D]:
    if not coEdge.isOpposedToEdge:
        return (coEdge.edge.startVertex.geometry, coEdge.edge.endVertex.geometry)
    else:
        return (coEdge.edge.endVertex.geometry, coEdge.edge.startVertex.geometry)

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes