How to draw circles on a sphere with given orientation? (Tangent to sphere)

How to draw circles on a sphere with given orientation? (Tangent to sphere)

Anonymous
Not applicable
1,375 Views
2 Replies
Message 1 of 3

How to draw circles on a sphere with given orientation? (Tangent to sphere)

Anonymous
Not applicable

Hi all,

 

I have a set of points coordinates in a .csv file (cartesian x,y,z). I also have a sphere.

I want to draw circles on that sphere whose center are my points, but I am only able to draw horizontal/vertical circles, without the good orientation.

 

======================

Relevant part of the code:

dlg = ui.createFileDialog()
dlg.title = 'Open CSV File'
dlg.filter = 'Comma Separated Values (*.csv);;All Files (*.*)'
if dlg.showOpen() != adsk.core.DialogResults.DialogOK :
return
 
filename = dlg.filename
with io.open(filename, 'r', encoding='utf-8-sig') as f:
points = adsk.core.ObjectCollection.create()
circles = adsk.core.ObjectCollection.create()
line = f.readline()
# initialize arrray data variable
data = []
while line:
pntStrArr = line.split(',')
for pntStr in pntStrArr:
try:
data.append(float(pntStr))
except:
break
 
if len(data) >= 3 :
point = adsk.core.Point3D.create(data[0], data[1], data[2])
root = design.rootComponent
sketch = root.sketches.add(root.xYConstructionPlane)
sketch.sketchPoints.add(point)
points.add(point)
circle = sketch.sketchCurves.sketchCircles.addByCenterRadius(point, 0.005)
circles.add(circle)
line = f.readline()
data.clear()
if points.count:
root = design.rootComponent
sketch = root.sketches.add(root.xYConstructionPlane)
sketch.sketchPoints.add(points)
sketch.sketchCurves.sketchFittedSplines.add(points)
sketch.sketchCurves.sketchCircles.addByCenterRadius(circles, 0.005)
else:
ui.messageBox('No valid points', title)
 
 
0 Likes
1,376 Views
2 Replies
Replies (2)
Message 2 of 3

BrianEkins
Mentor
Mentor

In Fusion, sketches are a bit weird in that they are 3D in that the sketch geometry can exist anywhere within the 3D sketch space but they behave the best when everything lying on the sketch X-Y plane (essentially 2D).  In the UI you can only create a circle on the X-Y plane of the sketch.  However, you can move and reorient it later.  The API has the same behavior.  Here's a bit of test code I wrote to test that workflow and it seems to work.  It creates a circle at the (0,0,0) of the sketch, which is also assumed to be the center of the sphere, and then uses the move method to position it at the location and orientation it should be at to lie on the sphere.  I found some code online to convert from longitude and latitude to the X, Y, Z position to calculate some test points.  Don't look too hard at that code because there are likely some mistakes but it works good enough for this test. 🙂 Here's the result.

 

sphereCircles.png

 

And here's the code.

def circleTest(context):
    app = adsk.core.Application.get()
    ui = app.userInterface
    try:
        design = adsk.fusion.Design.cast(app.activeProduct)
        root = adsk.fusion.Component.cast(design.rootComponent)

        sk = adsk.fusion.Sketch.cast(root.sketches.add(root.xYConstructionPlane))
        circles = adsk.fusion.SketchCircles.cast(sk.sketchCurves.sketchCircles)

        latitude = -math.pi * 0.25
        longitude = 0
        sphereRad = 5
        circleRad = 1
        height = math.sqrt(math.pow(sphereRad, 2) - math.pow(circleRad,2)) 
        center = adsk.core.Point3D.create(0,0,0)

        for lat_step in range(8):
            for long_step in range(3):
                # Create a circle on the X-Y plane centered at the origin
                circ = circles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), circleRad)

                # Convert the latitude and longitude to XYZ (ECEF)
                # https://en.wikipedia.org/wiki/Geographic_coordinate_conversion
                radSquare = math.pow(sphereRad, 2)
                nlat = radSquare / math.sqrt(radSquare * math.pow(math.cos(latitude), 2) + radSquare * math.pow(math.sin(latitude), 2))
                nlat = 0
                x = (nlat + height) * math.cos(latitude) * math.cos(longitude)
                y = (nlat + height) * math.cos(latitude) * math.sin(longitude)
                z = (nlat + height) * math.sin(latitude)

                # Create the Z vector along the vector defined by sphere center to the point.
                pnt = adsk.core.Point3D.create(x, y, z)
                zVec = center.vectorTo(pnt)
                zVec.normalize()

                # Create an arbitrary X axis that is not paralle with the Z axis.
                xVec = adsk.core.Vector3D.create(1, .05, 0.05)

                # Create the Y axis by crossing the Z and X vectors.
                yVec = zVec.crossProduct(xVec)
                yVec.normalize()

                # Create the good X axis by crossing the Y and Z vectors.
                xVec = yVec.crossProduct(zVec)
                xVec.normalize()

                # Create a matrix using the origin and vectors computed.
                mat = adsk.core.Matrix3D.create()
                mat.setWithCoordinateSystem(pnt, xVec, yVec, zVec)

                # Move the circle using the defined matrix.
                objs = adsk.core.ObjectCollection.create()
                objs.add(circ)
                sk.move(objs, mat)

                # Adjust the longitude for the next circle
                longitude = longitude + (math.pi * 0.25)
            
            # Reset the longitude angle.
            longitude = -math.pi * 0.25

            # Adjust the latitude for the set of longitude circles
            latitude = latitude + (math.pi * 0.25)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

  

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 3 of 3

Anonymous
Not applicable

While it needed some adjustments, I finally managed to get the same model. I also subsequently used the extrude function which worked well.  Thanks!

0 Likes