How can I use an edge as a profile for a not solid sweep (surface)?

How can I use an edge as a profile for a not solid sweep (surface)?

adminTCYL2
Enthusiast Enthusiast
694 Views
4 Replies
Message 1 of 5

How can I use an edge as a profile for a not solid sweep (surface)?

adminTCYL2
Enthusiast
Enthusiast

I use rotated sweeps as basis to draw electrical coils. This works best on lines or arcs and not good on splines. 

The basis curve is done by a formular. So I get points and normaly I would draw a spline along, but in this case it is better to draw arcs along. Then I do this rotated sweeps along the arcs. 

adminTCYL2_0-1631557766320.png

But there is a problem: Each surface has its own profile and they do not connect. 
To connect them to one surface I want to use the end-edge of an arc-sweep as profile for the next arc-sweep. 

In my script you see out comanded lines where I try this. But Fusion does not accept the edge as a profile. 
Does someone know a solution?

import adsk.core, adsk.fusion, adsk.cam, traceback, math

def run(context):
	ui = None
	try:
		app = adsk.core.Application.get()
		ui = app.userInterface
		design = app.activeProduct
		# Get the root component of the active design.
		root_comp = design.rootComponent
		# Create a new sketch on the xy plane.
		sketches = root_comp.sketches
		xyPlane = root_comp.xYConstructionPlane
		sketch = sketches.add(xyPlane)
		points = adsk.core.ObjectCollection.create() # Create an object collection for the points.
        

		windings = 10
		pointsPerRound = 4 # Number of points that splines are generated.
		i = -pointsPerRound*windings #Startwert, der in der Schleife runtergezählt wird
		r = 0.5
		h = 0


		while i <= 0:
			t = (math.pi/(pointsPerRound*windings))*i*2
			h = 1.5+((-r)*(math.sin(t*windings)))
			xCoord = (h)*(math.sin(t))
			yCoord = (h)*(math.cos(t))
			zCoord = ((-r)*(math.cos(t*windings)))
			points.add(adsk.core.Point3D.create(xCoord,yCoord,zCoord))
			i = i + 1
		
		#Combining the points to arcs
		arcs = adsk.core.ObjectCollection.create()
		for j in range(0,int((windings*pointsPerRound)/2)):
			arc = sketch.sketchCurves.sketchArcs.addByThreePoints(points[2*j],points[2*j+1],points[2*j+2])
			arcs.add(arc)
			profilStart = adsk.core.Point3D.create(points[2*j].x,points[2*j].y,points[2*j].z-0.2)
			profilEnd =   adsk.core.Point3D.create(points[2*j].x,points[2*j].y,points[2*j].z-0.01)
			profil=sketch.sketchCurves.sketchLines.addByTwoPoints(profilStart,profilEnd)

			"""
			# The right way would be: define a start profile for the sweep...
			if j==0:
				profilStart = adsk.core.Point3D.create(points[0].x,points[0].y,points[0].z-0.2)
				profilEnd =   adsk.core.Point3D.create(points[0].x,points[0].y,points[0].z-0.01)		
				profil=sketch.sketchCurves.sketchLines.addByTwoPoints(profilStart,profilEnd)
			# ..and then use the edge of the last sweep as profile for the next: 
			else:
				itemIndex = root_comp.bRepBodies.count-1
				body = root_comp.bRepBodies.item(itemIndex)
				profil=	body.edges.item(3)  #it is not clear witch of the four items
				sketch.add(profil)
			"""
			prof = root_comp.createOpenProfile(profil, False)
			path = root_comp.features.createPath(arc, False)
			sweeps = root_comp.features.sweepFeatures
			sweepInput1 = sweeps.createInput(prof, path, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
			sweepInput1.twistAngle = adsk.core.ValueInput.createByReal(100)
			sweepInput1.isSolid = False
			sweep = sweeps.add(sweepInput1)

		for j in range(0,10):
			arcs[j].startSketchPoint.merge(arcs[j+1].endSketchPoint)


	except:
		if ui:
			ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


 

0 Likes
Accepted solutions (1)
695 Views
4 Replies
Replies (4)
Message 2 of 5

kandennti
Mentor
Mentor
Accepted solution

Hi @adminTCYL2 .

 

It looked interesting, so I gave it a try.

 

I decided to create only one SketchLine, which would be the profile of the first Sweep, and use the edge of the previous Sweep for the rest of the Sweeps.

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback, math

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        design = app.activeProduct
        # Get the root component of the active design.
        root_comp = design.rootComponent

        windings = 10
        pointsPerRound = 4 # Number of points that splines are generated.
        i = -pointsPerRound*windings #Startwert, der in der Schleife runtergezählt wird
        r = 0.5
        h = 0

        # create points
        points = []
        while i <= 0:
            t = (math.pi/(pointsPerRound*windings))*i*2
            h = 1.5+((-r)*(math.sin(t*windings)))
            xCoord = (h)*(math.sin(t))
            yCoord = (h)*(math.cos(t))
            zCoord = ((-r)*(math.cos(t*windings)))
            points.append(
                adsk.core.Point3D.create(xCoord,yCoord,zCoord)
            )
            i = i + 1

        # create sketch
        sketches = root_comp.sketches
        xyPlane = root_comp.xYConstructionPlane
        sketch: adsk.fusion.Sketch = sketches.add(xyPlane)
        sketch.arePointsShown = False

        # create arcs
        sketch.isComputeDeferred = True
        sktArcs = sketch.sketchCurves.sketchArcs
        arcs = [sktArcs.addByThreePoints(p1, p2, p3) 
            for p1, p2, p3 in zip(points[0::2], points[1::2], points[2::2])]

        # create start line & OpenProfile
        line: adsk.fusion.SketchLine = sketch.sketchCurves.sketchLines.addByTwoPoints(
            adsk.core.Point3D.create(
                points[0].x,
                points[0].y,
                points[0].z - 0.2
            ),
            adsk.core.Point3D.create(
                points[0].x,
                points[0].y,
                points[0].z - 0.01
            )
        )
        profile: adsk.fusion.Profile = root_comp.createOpenProfile(line)
        sketch.isComputeDeferred = False

        # create paths
        paths = [root_comp.features.createPath(arc, False) for arc in arcs]

        # create SweepFeatureInput - This is only temporary.
        sweeps: adsk.fusion.SweepFeatures = root_comp.features.sweepFeatures
        twistAngle = adsk.core.ValueInput.createByReal(100)
        sweepIpt: adsk.fusion.SweepFeatureInput = sweeps.createInput(
            profile,
            paths[0],
            adsk.fusion.FeatureOperations.NewBodyFeatureOperation
        )
        sweepIpt.isSolid = False
        sweepIpt.twistAngle = twistAngle

        # create SweepFeature
        # Create a SweepFeature while modifying SweepFeatureInput.
        # Find the edge that will be the next profile from the SweepFeature.
        for path in paths:
            sweepIpt.profile = profile
            sweepIpt.path = path

            sweepFeat: adsk.fusion.SweepFeature = sweeps.add(sweepIpt)
            edge: adsk.fusion.BRepEdge = findNextProfileEdge(sweepFeat)

            profile = root_comp.createBRepEdgeProfile(edge, False)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def findNextProfileEdge(
    sweepFeat: adsk.fusion.SweepFeature) -> adsk.fusion.BRepEdge:

    profileGeo: adsk.core.Line3D = sweepFeat.profile.item(0).entity.geometry

    nextProfileEdge = None
    edge: adsk.fusion.BRepEdge
    for edge in sweepFeat.sideFaces[0].edges:
        if edge.geometry.objectType != 'adsk::core::Line3D':
            continue

        if not idEqualLine(profileGeo, edge.geometry):
            nextProfileEdge = edge
            break
    
    if not nextProfileEdge:
        raise ValueError("Cannot find the next profile!")

    return nextProfileEdge


def idEqualLine(
    l1: adsk.core.Line3D,
    l2: adsk.core.Line3D) -> bool:

    if not l1.isColinearTo(l2):
        return False

    p1: adsk.core.Point3D = l2.startPoint
    p2: adsk.core.Point3D = l2.endPoint
    if l1.startPoint.isEqualTo(p1):
        if l1.endPoint.isEqualTo(p2):
            return True
    elif l1.startPoint.isEqualTo(p2):
        if l1.endPoint.isEqualTo(p1):
            return True

    return False

 

I don't know about these shapes, but since the Arcs are not smoothly connected, the resulting Surface is not smooth either.

1.png

 

 

Also, the first and last edges were not connected.
I think it was a problem with the twist angle calculation, but I couldn't figure out what was right.

2.png

0 Likes
Message 3 of 5

kandennti
Mentor
Mentor

@adminTCYL2 .

 

I forgot to write down the most important thing.
It is the Component.createBRepEdgeProfile method that gets the profile from the edge.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-ca25aae8-7ca2-4048-b912-e980774a736e 

Message 4 of 5

adminTCYL2
Enthusiast
Enthusiast

Thank you kandennti, that is a great peace of work!
With the Component.createBRepEdgeProfile method I can now use edges as profiles by simply write: 

prof = root_comp.createBRepEdgeProfile(edgeFalse)

But using it in my script worked just for the first three arcs. Then the body.edges.item(2) was the wrong one... somehow the item-number of the ages change by position of the surface... and so further arcs failed. 
I wonder how you managed to solve this problem! I will try to understand your code and give further feedback. 

adminTCYL2_0-1631606792764.png

 



Message 5 of 5

adminTCYL2
Enthusiast
Enthusiast

Hi Kandennti, 
I tested your script. It works very fine. The only change I did was not to calculate all parts (arcs) and enhanced the calculated points so that the arcs are short and the coil is very near to the mathematical optimum. 
As you see this script allows very many rotations and can be basis for drawing electrical coils along the edge of the sweeps. I accepted your solution, because this script is your success not mine. I would not have been able to write this nice function to choose allways the right edge. 

adminTCYL2_0-1631609618961.png

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback, math

def run(context):
	ui = None
	try:
		# Settings:
		windings = 10
		pointsPerRound = 20 # Number of points that splines are generated.
		calculatedArcs = 20 # All are calculated by windings*pointsPerRound/2
		r = 0.5
		h = 0
		rotations=100

		app = adsk.core.Application.get()
		ui = app.userInterface
		design = app.activeProduct
		root_comp = design.rootComponent

		# create points
		points = []
		i = -pointsPerRound*windings
		while i <= 0:
			t = (math.pi/(pointsPerRound*windings))*i*2
			h = 1.5+((-r)*(math.sin(t*windings)))
			xCoord = (h)*(math.sin(t))
			yCoord = (h)*(math.cos(t))
			zCoord = ((-r)*(math.cos(t*windings)))
			points.append(
				adsk.core.Point3D.create(xCoord,yCoord,zCoord)
			)
			i = i + 1

		# create sketch
		sketches = root_comp.sketches
		xyPlane = root_comp.xYConstructionPlane
		sketch: adsk.fusion.Sketch = sketches.add(xyPlane)
		sketch.arePointsShown = False

		# create arcs
		sketch.isComputeDeferred = True
		sktArcs = sketch.sketchCurves.sketchArcs
		arcs = [sktArcs.addByThreePoints(p1, p2, p3) 
			for p1, p2, p3 in zip(points[0::2], points[1::2], points[2::2])]

		# create start line & OpenProfile
		line: adsk.fusion.SketchLine = sketch.sketchCurves.sketchLines.addByTwoPoints(
			adsk.core.Point3D.create(
				points[0].x,
				points[0].y,
				points[0].z - 0.2
			),
			adsk.core.Point3D.create(
				points[0].x,
				points[0].y,
				points[0].z - 0.01
			)
		)
		profile: adsk.fusion.Profile = root_comp.createOpenProfile(line)
		sketch.isComputeDeferred = False

		# create paths
		paths = [root_comp.features.createPath(arc, False) for arc in arcs]

		# create SweepFeatureInput - This is only temporary.
		sweeps: adsk.fusion.SweepFeatures = root_comp.features.sweepFeatures
		twistAngle = adsk.core.ValueInput.createByReal(rotations)
		sweepIpt: adsk.fusion.SweepFeatureInput = sweeps.createInput(
			profile,
			paths[0],
			adsk.fusion.FeatureOperations.NewBodyFeatureOperation
		)
		sweepIpt.isSolid = False
		sweepIpt.twistAngle = twistAngle

		# create SweepFeature
		# Create a SweepFeature while modifying SweepFeatureInput.
		# Find the edge that will be the next profile from the SweepFeature.
		for j in range (0,calculatedArcs):
		#for path in paths:
			sweepIpt.profile = profile
			sweepIpt.path = paths[j] # =path
			sweepFeat: adsk.fusion.SweepFeature = sweeps.add(sweepIpt)
			edge: adsk.fusion.BRepEdge = findNextProfileEdge(sweepFeat)

			profile = root_comp.createBRepEdgeProfile(edge, False)

	except:
		if ui:
			ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def findNextProfileEdge(
    sweepFeat: adsk.fusion.SweepFeature) -> adsk.fusion.BRepEdge:

    profileGeo: adsk.core.Line3D = sweepFeat.profile.item(0).entity.geometry

    nextProfileEdge = None
    edge: adsk.fusion.BRepEdge
    for edge in sweepFeat.sideFaces[0].edges:
        if edge.geometry.objectType != 'adsk::core::Line3D':
            continue

        if not idEqualLine(profileGeo, edge.geometry):
            nextProfileEdge = edge
            break
    
    if not nextProfileEdge:
        raise ValueError("Cannot find the next profile!")

    return nextProfileEdge


def idEqualLine(
    l1: adsk.core.Line3D,
    l2: adsk.core.Line3D) -> bool:

    if not l1.isColinearTo(l2):
        return False

    p1: adsk.core.Point3D = l2.startPoint
    p2: adsk.core.Point3D = l2.endPoint
    if l1.startPoint.isEqualTo(p1):
        if l1.endPoint.isEqualTo(p2):
            return True
    elif l1.startPoint.isEqualTo(p2):
        if l1.endPoint.isEqualTo(p1):
            return True

    return False