├── .gitignore ├── ImportCSVPoints.manifest ├── ImportCSVPoints.py ├── LICENSE ├── README.md ├── images ├── filedialog.png ├── importcsvpoints-dialog-solidbody-sphere-simple3D.png ├── importcsvpoints-dialog-solidbody-sphere.png ├── importcsvpoints-dialog-solidbody.png ├── importcsvpoints-dialog.png ├── insert-dropdown.png ├── insert-tooltip.png ├── simple2D_pipes.png ├── sketcher_vr_BoxVaseFlowers.png ├── sketcher_vr_Simple_anim.gif ├── sketcher_vr_Simple_anim.psd ├── sketcher_vr_Simple_back.png ├── sketcher_vr_Simple_front.png ├── sketcher_vr_Simple_left.png ├── sketcher_vr_Simple_pipes.png ├── sketcher_vr_Simple_right.png └── spiralcube_sketch.png ├── patterns.py ├── pipe.py ├── resources ├── 16x16-disabled.png ├── 16x16.png ├── 32x32-disabled.png ├── 32x32.png ├── 32x32@2x.png ├── 64x64.ai ├── tooltip.png └── tooltip.psd └── samples ├── circles2D.csv ├── simple2D.csv ├── simple2D_pipes.csv ├── simple3D.csv ├── simple3D_pipes.csv ├── sketcher_vr_BoxVaseFlowers.csv ├── sketcher_vr_Simple.csv ├── sketcher_vr_Simple_pipes.csv ├── sketcher_vr_Simple_pipes_solid.csv ├── spiral.csv └── spiralcube.csv /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .vscode/ 3 | .env 4 | 5 | *.log 6 | 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | .localized 11 | 12 | .Spotlight-V100 13 | .Trashes 14 | .AppleDB 15 | .AppleDesktop 16 | Network Trash Folder 17 | Temporary Items 18 | .apdisk 19 | $RECYCLE.BIN/ 20 | 21 | Thumbs.db 22 | ehthumbs.db 23 | 24 | Desktop.ini 25 | -------------------------------------------------------------------------------- /ImportCSVPoints.manifest: -------------------------------------------------------------------------------- 1 | { 2 | "autodeskProduct": "Fusion360", 3 | "type": "addin", 4 | "id": "0f516f0e-e662-44a8-8f66-1b378ea2176c", 5 | "author": "Hans Kellner", 6 | "description": "Fusion 360 addin for importing a set of points from a CSV file and creating points, lines, or splines in a sketch.", 7 | "version": "2.0.0", 8 | "runOnStartup": false, 9 | "supportedOS": "windows|mac", 10 | "editEnabled": true 11 | } -------------------------------------------------------------------------------- /ImportCSVPoints.py: -------------------------------------------------------------------------------- 1 | #Author-Hans Kellner 2 | #Description-Import X,Y,Z values from a CSV file to create points, or lines, or splines within a sketch. 3 | 4 | import adsk.core, adsk.fusion, traceback, math, random 5 | 6 | from . import patterns 7 | from . import pipe 8 | from enum import Enum 9 | 10 | # CONSTANTS 11 | 12 | class Sketch_Style(Enum): 13 | SKETCH_POINTS = 0 14 | SKETCH_LINES = 1 15 | SKETCH_FITTED_SPLINES = 2 16 | SKETCH_SOLID_BODY = 3 17 | LAST_STYLE = 3 18 | 19 | UNIT_STRINGS = { 20 | 'mm': 'Millimeter', 21 | 'cm': 'Centimeter', 22 | 'meter': 'Meter', 23 | 'in': 'Inch', 24 | 'ft': 'Foot' 25 | } 26 | 27 | _IMPORT_CSV_POINTS_CMD_ID = 'hanskellner_insert_csv_points_id' 28 | 29 | _INSERT_PANEL_ID = 'InsertPanel' 30 | 31 | _DROPDOWN_INPUT_ID_UNIT = 'unitDropDownInputId' 32 | _DROPDOWN_INPUT_ID_STYLE = 'styleDropDownInputId' 33 | _SELECTION_INPUT_ID_SOLID_BODY = 'solidBodySelectionInputId' 34 | _SELECTION_INPUT_ID_SKETCH = 'sketchSelectionInputId' 35 | _DROPDOWN_INPUT_ID_CONSTRUCTION_PLANE = 'constructionPlaneDropDownInputId' 36 | 37 | 38 | _CONSTRUCTION_PLANE_XY = "XY Plane" 39 | _CONSTRUCTION_PLANE_XZ = "XZ Plane" 40 | _CONSTRUCTION_PLANE_YZ = "YZ Plane" 41 | 42 | # GLOBALS 43 | 44 | # event handlers to keep them referenced for the duration of the command 45 | _app = adsk.core.Application.cast(None) 46 | _ui = adsk.core.UserInterface.cast(None) 47 | 48 | # Global set of event handlers to keep them referenced for the duration of the command 49 | _handlers = [] 50 | 51 | # Units to use for imported points 52 | _unit = 'cm' 53 | 54 | # File to load 55 | _csvFilename = '' 56 | 57 | # Style of sketch entities to create 58 | _style = Sketch_Style.SKETCH_LINES 59 | 60 | # Which solid body selected 61 | _solidBodyToClone = None 62 | 63 | # If a sketch is selected, this is the name 64 | _selectedSketchName = '' 65 | 66 | # Which construction plane to place sketch when a sketch isn't specified 67 | _constructionPlane = _CONSTRUCTION_PLANE_XY 68 | 69 | # Command Inputs 70 | _unitDropDownInput = adsk.core.DropDownCommandInput.cast(None) 71 | _styleDropDownInput = adsk.core.DropDownCommandInput.cast(None) 72 | _sketchSelectionInput = adsk.core.SelectionCommandInput.cast(None) 73 | _constructionPlaneDropDownInput = adsk.core.DropDownCommandInput.cast(None) 74 | _solidBodySelectionInput = adsk.core.DropDownCommandInput.cast(None) 75 | 76 | 77 | # Get the selected sketch name; otherwise an empty string 78 | def getSelectedSketchName(): 79 | if _sketchSelectionInput.selectionCount == 1: 80 | theSelection = _sketchSelectionInput.selection(0) 81 | 82 | if theSelection.entity.objectType == adsk.fusion.Sketch.classType(): 83 | return theSelection.entity.name 84 | 85 | # Nothing selected so no sketch name 86 | return '' 87 | 88 | # Get the selected entity (body or component) 89 | def getSelectedEntity(): 90 | if _solidBodySelectionInput.selectionCount == 1: 91 | return _solidBodySelectionInput.selection(0).entity 92 | else: 93 | return None 94 | 95 | # Get the selected entity style to create 96 | def getSelectedStyle(): 97 | return _styleDropDownInput.selectedItem.index 98 | 99 | 100 | # Converts a value from the user selected unit to 'cm' 101 | # Returns a pair (bool: True on success; otherwise false, Value) 102 | def convertValue(value): 103 | global _app, _ui 104 | 105 | design = _app.activeProduct 106 | newVal = design.unitsManager.convert(value, _unit, 'cm') 107 | 108 | # unitsManager.convert() returns -1 AND GetLastError() returns ExpressionError in the event of an error. 109 | if newVal == -1: 110 | (errReturnValue, errDescription) = _app.getLastError() 111 | if errReturnValue == adsk.fusion.ExpressionError: 112 | return (False, 0) 113 | 114 | return (True, newVal) 115 | 116 | # Returns total count of points in all lines 117 | def totalPointsInLines(lines): 118 | count = 0 119 | if lines != None: 120 | for pts in lines: 121 | count += len(pts) 122 | return count 123 | 124 | # Event handler for the execute event. 125 | class MyCommandExecuteHandler(adsk.core.CommandEventHandler): 126 | def __init__(self): 127 | super().__init__() 128 | def notify(self, args): 129 | eventArgs = adsk.core.CommandEventArgs.cast(args) 130 | 131 | global _app, _ui, _selectedSketchName, _constructionPlane, _solidBodyToClone, _csvFilename 132 | 133 | design = _app.activeProduct 134 | rootComp = design.rootComponent 135 | 136 | try: 137 | 138 | # Create file dialog to prompt for CSV file 139 | fileDialog = _ui.createFileDialog() 140 | fileDialog.isMultiSelectEnabled = False 141 | fileDialog.title = "Select Points CSV File" 142 | fileDialog.filter = 'CSV files (*.csv);;All files (*.*)' 143 | fileDialog.filterIndex = 0 144 | dialogResult = fileDialog.showOpen() 145 | if dialogResult != adsk.core.DialogResults.DialogOK: 146 | _csvFilename = '' 147 | return 148 | 149 | # This is our filename 150 | _csvFilename = fileDialog.filename 151 | 152 | # Set styles of progress dialog. 153 | progressDialog = _ui.createProgressDialog() 154 | progressDialog.cancelButtonText = 'Cancel' 155 | progressDialog.isBackgroundTranslucent = False 156 | progressDialog.isCancelButtonShown = True 157 | 158 | # Show progress dialog 159 | progressDialog.show('Importing CSV', 'Loading... %v', 0, 1000, 1) 160 | 161 | lineCount = 0 162 | skippingBlanks = False # True when skipping a set of blank lines 163 | 164 | lines = [] # list of point lists 165 | points3D = [] # Current Point3D list 166 | CirclePoints3D = [] # Circle centre point list 167 | CircleDiameters = [] # Circle diameter list 168 | 169 | cmdCreatePipes = False 170 | argCreatePipesOuterRadius = 1 171 | argCreatePipesInnerRadius = 0.5 # > 0 means hollow 172 | 173 | # Read the csv file line by line. 174 | file = open(_csvFilename) 175 | for line in file: 176 | 177 | line = line.strip() 178 | 179 | # Is this line empty? Note, also check for the case where the line contains the separators but no values. 180 | # This can occur when some apps, such as Excel, exports empty rows. 181 | if line == '' or line == ',,' or line == ',': 182 | skippingBlanks = True 183 | 184 | # A blank line indicates a break in the point sequence and to start 185 | # a new set of points. For example, for creating multiple lines. 186 | if len(points3D) > 0: 187 | lines.append(points3D) 188 | points3D = [] 189 | 190 | elif line[0] == '#': 191 | pass # Skip comment lines 192 | 193 | else: 194 | skippingBlanks = False 195 | 196 | # Get the values from the csv file. 197 | pieces = line.split(',') 198 | 199 | if len(pieces) == 0: 200 | progressDialog.hide() 201 | _ui.messageBox("Invalid line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 202 | return 203 | 204 | # check for a specific command in first piece 205 | if pieces[0] == 'spiral': 206 | 207 | # Need to end previous set? 208 | if len(points3D) > 0: 209 | lines.append(points3D) 210 | points3D = [] 211 | 212 | # spiral needs 5 arguments: numArms, numPointsPerArm, armsOffset, rateExpansion, zStep 213 | if len(pieces) != 6: 214 | progressDialog.hide() 215 | _ui.messageBox("Invalid 'spiral' at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 216 | return 217 | 218 | linesSpiral = patterns.generateSpiral(int(pieces[1]), int(pieces[2]), float(pieces[3]), float(pieces[3]), float(pieces[3])) 219 | if linesSpiral == None: 220 | progressDialog.hide() 221 | _ui.messageBox("Invalid parameters for 'spiral' at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 222 | return 223 | 224 | lines.extend( linesSpiral ) 225 | 226 | elif pieces[0] == 'spiralcube': 227 | 228 | # Need to end previous set? 229 | if len(points3D) > 0: 230 | lines.append(points3D) 231 | points3D = [] 232 | 233 | # spiral cube needs 3 arguments: pointCount, rotationInRadians, lengthGrow 234 | if len(pieces) != 4: 235 | progressDialog.hide() 236 | _ui.messageBox("Invalid 'spiralcube' line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 237 | return 238 | 239 | linesSpiralCube = patterns.generateSpiralCube(int(pieces[1]), float(pieces[2]), float(pieces[3])) 240 | if linesSpiralCube == None: 241 | progressDialog.hide() 242 | _ui.messageBox("Invalid parameters for 'spiralcube' at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 243 | return 244 | 245 | lines.extend( linesSpiralCube ) 246 | 247 | # Command to create pipes for all of the lines/splines read 248 | # REVIEW: HACK: This is a hack to allow creating pipes. 249 | elif pieces[0] == 'pipes': 250 | 251 | # Need to end previous set? 252 | if len(points3D) > 0: 253 | lines.append(points3D) 254 | points3D = [] 255 | 256 | # pipe needs 1 or 2 arguments: outer radius, [inner radius] 257 | if (len(pieces) < 2 or len(pieces) > 3): 258 | progressDialog.hide() 259 | _ui.messageBox("Invalid 'pipes' line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 260 | return 261 | 262 | cmdCreatePipes = True 263 | (outerValid, argCreatePipesOuterRadius) = convertValue(float(pieces[1])) 264 | 265 | if (len(pieces) == 3): 266 | (innerValid, argCreatePipesInnerRadius) = convertValue(float(pieces[2])) 267 | else: 268 | (innerValid, argCreatePipesInnerRadius) = (True, 0) 269 | 270 | if not outerValid or not innerValid: 271 | progressDialog.hide() 272 | _ui.messageBox("Invalid pipes radius value at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 273 | return 274 | 275 | # Command to create circles 276 | elif pieces[0] == 'circle': 277 | 278 | # Need to end previous set? 279 | if len(points3D) > 0: 280 | lines.append(points3D) 281 | points3D = [] 282 | 283 | # circle needs 3 or 4 arguments: center point [x, y, z] and radius 284 | if (len(pieces) < 4 or len(pieces) > 5): 285 | progressDialog.hide() 286 | _ui.messageBox("Invalid 'circle' line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 287 | return 288 | 289 | (xValid, x) = convertValue(float(pieces[1])) 290 | (yValid, y) = convertValue(float(pieces[2])) 291 | 292 | if (len(pieces) == 4): 293 | (zValid, z) = (True, 0) 294 | (radiusValid, radius) = convertValue(float(pieces[3])) 295 | else: 296 | (zValid, z) = convertValue(float(pieces[3])) 297 | (radiusValid, radius) = convertValue(float(pieces[4])) 298 | 299 | if not xValid or not yValid or not zValid or not radiusValid: 300 | progressDialog.hide() 301 | _ui.messageBox("Invalid number at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 302 | return 303 | 304 | CirclePoints3D.append(adsk.core.Point3D.create(x,y,z)) 305 | CircleDiameters.append(radius) 306 | 307 | if len(lines) == 0: #Workaround to add at least one point to lines for the script not to stop #TODO: Remove 308 | points3D.append(adsk.core.Point3D.create(0,0,0)) 309 | lines.append(points3D) 310 | points3D = [] 311 | 312 | else: 313 | 314 | if (len(pieces) < 2 or len(pieces) > 3): 315 | progressDialog.hide() 316 | _ui.messageBox("No 2d or 3d point at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 317 | return 318 | 319 | (xValid, x) = convertValue(float(pieces[0])) 320 | (yValid, y) = convertValue(float(pieces[1])) 321 | 322 | if (len(pieces) == 3): 323 | (zValid, z) = convertValue(float(pieces[2])) 324 | else: 325 | (zValid, z) = (True, 0) 326 | 327 | if not xValid or not yValid or not zValid: 328 | progressDialog.hide() 329 | _ui.messageBox("Invalid number at line: {}".format(lineCount) + "\nCSV file: {}".format(_csvFilename)) 330 | return 331 | 332 | # Save this point 333 | points3D.append(adsk.core.Point3D.create(x,y,z)) 334 | 335 | lineCount = lineCount + 1 336 | 337 | # If progress dialog is cancelled, stop drawing. 338 | if progressDialog.wasCancelled: 339 | break 340 | 341 | # Update progress value of progress dialog 342 | progressDialog.progressValue = lineCount % 100 343 | 344 | # end line loop. Check if a set if points waiting to be added. 345 | if len(points3D) > 0: 346 | lines.append(points3D) 347 | 348 | # Hide the progress dialog at the end. 349 | progressDialog.hide() 350 | 351 | # Empty file then just exit 352 | if len(lines) == 0: 353 | _ui.messageBox("No points found in CSV file: {}".format(_csvFilename)) 354 | return 355 | 356 | # Creating solid bodies? 357 | isSolidBodyStyle = (Sketch_Style(_style) == Sketch_Style.SKETCH_SOLID_BODY) 358 | if isSolidBodyStyle: 359 | 360 | totalPonts = totalPointsInLines(lines) 361 | 362 | # Show progress dialog 363 | progressDialog.show('Generating Bodies', 'Creating %v of %m (%p)', 0, totalPonts, 1) 364 | 365 | bodyToClone = adsk.fusion.BRepBody.cast(_solidBodyToClone) 366 | 367 | bodyToClonePos = None 368 | 369 | newComp = rootComp.occurrences.addNewComponent(adsk.core.Matrix3D.create()) 370 | newComp.component.name = 'Import CSV Points' 371 | 372 | # Check to see if the body is in the root component or another one. 373 | #target = None 374 | if bodyToClone.assemblyContext: 375 | # It's in another component. 376 | target = bodyToClone.assemblyContext # Occurrence 377 | 378 | # Where is the body located? 379 | bodyToClonePos = target.transform.translation 380 | else: 381 | # It's in the root component. 382 | target = rootComp # Component 383 | 384 | for iLine in range(len(lines)): 385 | 386 | if (lines[iLine] == None or len(lines[iLine]) == 0): 387 | continue 388 | 389 | # For each point, create a copy of the prototype body 390 | linePoints = lines[iLine] 391 | for iPt in range(len(linePoints)): 392 | 393 | pt = linePoints[iPt] 394 | 395 | # If point is not at 0 then copy body and move to location 396 | # Otherwise, keep the existing object so we don't 397 | if (pt.x != 0 or pt.y != 0 or pt.z != 0): 398 | 399 | # Create the copy. 400 | newBody = bodyToClone.copyToComponent(newComp) #target) 401 | 402 | # Move the mew body (note, relative move) 403 | tx = adsk.core.Matrix3D.create() 404 | tx.translation = adsk.core.Vector3D.create(pt.x, pt.y, pt.z) 405 | bodyColl = adsk.core.ObjectCollection.create() 406 | bodyColl.add(newBody) 407 | moveInput = rootComp.features.moveFeatures.createInput(bodyColl, tx) 408 | moveFeat = rootComp.features.moveFeatures.add(moveInput) 409 | 410 | # If progress dialog is cancelled, stop drawing. 411 | if progressDialog.wasCancelled: 412 | break 413 | 414 | # Update progress value of progress dialog 415 | progressDialog.progressValue = iLine 416 | 417 | if progressDialog.wasCancelled: 418 | break 419 | 420 | else: # Sketch based 421 | 422 | # Show progress dialog 423 | progressDialog.show('Generating Entities', 'Creating %v of %m (%p)', 0, len(lines), 1) 424 | 425 | theSketch = None 426 | 427 | if _selectedSketchName != '': 428 | theSketch = rootComp.sketches.itemByName(_selectedSketchName) 429 | 430 | if theSketch == None: 431 | # Which plane if no sketch? 432 | # xYConstructionPlane, xZConstructionPlane, yZConstructionPlane 433 | plane = rootComp.xYConstructionPlane 434 | if _constructionPlane == _CONSTRUCTION_PLANE_XZ: 435 | plane = rootComp.xZConstructionPlane 436 | elif _constructionPlane == _CONSTRUCTION_PLANE_YZ: 437 | plane = rootComp.yZConstructionPlane 438 | 439 | theSketch = rootComp.sketches.add(plane) 440 | theSketch.name = "CSV Points - " + theSketch.name 441 | 442 | theSketch.isComputeDeferred = True # Help to speed up import 443 | wereProfilesShown = theSketch.areProfilesShown # REVIEW: Still testing if this improves performace 444 | theSketch.areProfilesShown = False 445 | 446 | new_sketch_lines = [] 447 | 448 | # Add sketch entities 449 | if Sketch_Style(_style) == Sketch_Style.SKETCH_FITTED_SPLINES: 450 | 451 | for iLine in range(len(lines)): 452 | 453 | if (lines[iLine] == None or len(lines[iLine]) == 0): 454 | continue 455 | 456 | # Create an object collection for the line points. 457 | linePoints = adsk.core.ObjectCollection.create() 458 | 459 | # Add the points the spline will fit through. 460 | for pt in lines[iLine]: 461 | linePoints.add(pt) 462 | 463 | # Create the spline. 464 | theSketchLine = theSketch.sketchCurves.sketchFittedSplines.add(linePoints) 465 | new_sketch_lines.append(theSketchLine) 466 | 467 | # If progress dialog is cancelled, stop drawing. 468 | if progressDialog.wasCancelled: 469 | break 470 | 471 | # Update progress value of progress dialog 472 | progressDialog.progressValue = iLine 473 | 474 | else: 475 | sketch_points = theSketch.sketchPoints 476 | sketch_lines = theSketch.sketchCurves.sketchLines 477 | 478 | for iLine in range(len(lines)): 479 | 480 | if (lines[iLine] == None or len(lines[iLine]) == 0): 481 | continue 482 | 483 | theFirstSketchLine = None 484 | 485 | linePoints = lines[iLine] 486 | linePointsCount = len(linePoints) 487 | for iPt in range(linePointsCount): 488 | 489 | if Sketch_Style(_style) == Sketch_Style.SKETCH_POINTS: 490 | sketch_points.add(linePoints[iPt]) 491 | 492 | elif Sketch_Style(_style) == Sketch_Style.SKETCH_LINES: 493 | if iPt == 1: 494 | theSketchLine = sketch_lines.addByTwoPoints(linePoints[iPt-1], linePoints[iPt]) 495 | new_sketch_lines.append(theSketchLine) 496 | theFirstSketchLine = theSketchLine 497 | if iPt > 1: 498 | # Use previous sketch line's end point to start next line. Otherwise they won't 499 | # be connected lines. We also need to check if this is the last line and if it 500 | # has the same endpoint location as the first line's start point. If so then we 501 | # need to use the starting lines point as the endpoint of this line. 502 | lineEndPoint = None 503 | if linePoints[iPt].x == linePoints[0].x and linePoints[iPt].y == linePoints[0].y and linePoints[iPt].z == linePoints[0].z: 504 | lineEndPoint = theFirstSketchLine.startSketchPoint 505 | else: 506 | lineEndPoint = linePoints[iPt] 507 | 508 | theSketchLine = sketch_lines.addByTwoPoints(theSketchLine.endSketchPoint, lineEndPoint) 509 | # REVIEW: Only pass first line and then use "isChain" when creating feature.path 510 | #new_sketch_lines.append(theSketchLine) 511 | 512 | # If progress dialog is cancelled, stop drawing. 513 | if progressDialog.wasCancelled: 514 | break 515 | 516 | # Update progress value of progress dialog 517 | progressDialog.progressValue = iLine 518 | 519 | # Draw circles 520 | if len(CirclePoints3D) > 0: 521 | sketch_circles = theSketch.sketchCurves.sketchCircles 522 | for iPt in range(len(CirclePoints3D)): 523 | sketch_circles.addByCenterRadius(CirclePoints3D[iPt], CircleDiameters[iPt]) 524 | 525 | # Done creating sketch entities 526 | theSketch.isComputeDeferred = False 527 | theSketch.areProfilesShown = wereProfilesShown 528 | 529 | # Request to create pipes and were any skecth lines added? 530 | if cmdCreatePipes and len(new_sketch_lines) > 0: 531 | pipe.createPipesOnLines(_app, _ui, new_sketch_lines, argCreatePipesOuterRadius, argCreatePipesInnerRadius) 532 | 533 | # Hide the progress dialog at the end. 534 | progressDialog.hide() 535 | 536 | except: 537 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 538 | 539 | 540 | # Event handler that reacts to any changes the user makes to any of the command inputs. 541 | class MyCommandInputChangedHandler(adsk.core.InputChangedEventHandler): 542 | def __init__(self): 543 | super().__init__() 544 | def notify(self, args): 545 | try: 546 | global _app, _ui, _unit, _style, _constructionPlane, _selectedSketchName, _solidBodyToClone 547 | global _constructionPlaneDropDownInput, _unitDropDownInput, _styleDropDownInput 548 | 549 | des = adsk.fusion.Design.cast(_app.activeProduct) 550 | 551 | eventArgs = adsk.core.InputChangedEventArgs.cast(args) 552 | inputs = eventArgs.inputs 553 | changedInput = eventArgs.input 554 | 555 | # Need to know these anytime something changes 556 | _style = getSelectedStyle() 557 | isSolidBodyStyle = (Sketch_Style(_style) == Sketch_Style.SKETCH_SOLID_BODY) 558 | 559 | _solidBodyToClone = getSelectedEntity() 560 | isSolidBodySelected = isSolidBodyStyle and (_solidBodyToClone != None) 561 | 562 | if changedInput.id == _SELECTION_INPUT_ID_SOLID_BODY: 563 | pass 564 | 565 | if changedInput.id == _SELECTION_INPUT_ID_SKETCH: 566 | _selectedSketchName = getSelectedSketchName() 567 | 568 | elif changedInput.id == _DROPDOWN_INPUT_ID_CONSTRUCTION_PLANE: 569 | _constructionPlane = _constructionPlaneDropDownInput.selectedItem.name 570 | 571 | elif changedInput.id == _DROPDOWN_INPUT_ID_UNIT: 572 | unitName = _unitDropDownInput.selectedItem.name 573 | for keyUnit, valUnit in UNIT_STRINGS.items(): 574 | if valUnit == unitName: 575 | _unit = keyUnit 576 | break 577 | 578 | elif changedInput.id == _DROPDOWN_INPUT_ID_STYLE: 579 | pass 580 | 581 | # Update visiblity/enabled 582 | 583 | _solidBodySelectionInput.isVisible = isSolidBodyStyle 584 | if isSolidBodyStyle: 585 | _solidBodySelectionInput.setSelectionLimits(1, 1) 586 | else: 587 | _solidBodySelectionInput.setSelectionLimits(0) 588 | 589 | _sketchSelectionInput.isVisible = not isSolidBodyStyle 590 | 591 | _constructionPlaneDropDownInput.isVisible = not isSolidBodyStyle 592 | _constructionPlaneDropDownInput.isEnabled = (_selectedSketchName == '') 593 | 594 | except: 595 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 596 | 597 | 598 | # Event handler that reacts to when the command is destroyed. This terminates the script. 599 | class MyCommandDestroyHandler(adsk.core.CommandEventHandler): 600 | def __init__(self): 601 | super().__init__() 602 | def notify(self, args): 603 | try: 604 | # When the command is done, terminate the script 605 | # This will release all globals which will remove all event handlers 606 | #adsk.terminate() 607 | pass 608 | except: 609 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 610 | 611 | 612 | # Event handler that reacts when the command definitio is executed which 613 | # results in the command being created and this event being fired. 614 | class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): 615 | def __init__(self): 616 | super().__init__() 617 | def notify(self, args): 618 | try: 619 | global _app, _ui, _handlers, _unit, _csvFilename 620 | global _unitDropDownInput, _styleDropDownInput, _sketchSelectionInput, _constructionPlaneDropDownInput, _solidBodySelectionInput 621 | 622 | design = _app.activeProduct 623 | if not design: 624 | _ui.messageBox('No active Fusion design', 'No Design') 625 | return 626 | 627 | # Get the command that was created. 628 | cmd = adsk.core.Command.cast(args.command) 629 | 630 | # Connect to the command destroyed event. 631 | onDestroy = MyCommandDestroyHandler() 632 | cmd.destroy.add(onDestroy) 633 | _handlers.append(onDestroy) 634 | 635 | # Connect to the input changed event. 636 | onInputChanged = MyCommandInputChangedHandler() 637 | cmd.inputChanged.add(onInputChanged) 638 | _handlers.append(onInputChanged) 639 | 640 | # Get the user's current units 641 | _unit = design.unitsManager.defaultLengthUnits 642 | 643 | # Get the CommandInputs collection associated with the command. 644 | inputs = cmd.commandInputs 645 | 646 | # Create image input. 647 | #inputs.addImageCommandInput('image', 'Image', "resources/help.png") 648 | 649 | # Dropdown for unit used in CSV file 650 | _unitDropDownInput = inputs.addDropDownCommandInput(_DROPDOWN_INPUT_ID_UNIT, 'Units', adsk.core.DropDownStyles.TextListDropDownStyle) 651 | for keyUnit, valUnit in UNIT_STRINGS.items(): 652 | _unitDropDownInput.listItems.add(valUnit, (_unit == keyUnit)) 653 | 654 | isSolidBodyStyle = (Sketch_Style(_style) == Sketch_Style.SKETCH_SOLID_BODY) 655 | 656 | # Dropdown for the type of sketch entity to create 657 | _styleDropDownInput = inputs.addDropDownCommandInput(_DROPDOWN_INPUT_ID_STYLE, 'Style', adsk.core.DropDownStyles.TextListDropDownStyle) 658 | styleInputListItems = _styleDropDownInput.listItems 659 | styleInputListItems.add('Points', (Sketch_Style(_style) == Sketch_Style.SKETCH_POINTS)) 660 | styleInputListItems.add('Lines', (Sketch_Style(_style) == Sketch_Style.SKETCH_LINES)) 661 | styleInputListItems.add('Fitted Splines', (Sketch_Style(_style) == Sketch_Style.SKETCH_FITTED_SPLINES)) 662 | styleInputListItems.add('Solid Body', isSolidBodyStyle) 663 | 664 | # Selection of body to clone for each point 665 | _solidBodySelectionInput = inputs.addSelectionInput(_SELECTION_INPUT_ID_SOLID_BODY, 'Body to Clone', 'Select a body to clone for each point') 666 | _solidBodySelectionInput.addSelectionFilter('Bodies') 667 | _solidBodySelectionInput.setSelectionLimits(1 if isSolidBodyStyle else 0, 1) # HACK: OK btn still checks hidden control state 668 | _solidBodySelectionInput.isVisible = isSolidBodyStyle 669 | 670 | # Optional: Selection of sketch to add entities 671 | _sketchSelectionInput = inputs.addSelectionInput(_SELECTION_INPUT_ID_SKETCH, 'Sketch', 'Select a sketch or none to create a new one') 672 | _sketchSelectionInput.addSelectionFilter('Sketches') 673 | _sketchSelectionInput.setSelectionLimits(0, 1) 674 | _sketchSelectionInput.isVisible = not isSolidBodyStyle 675 | 676 | _constructionPlaneDropDownInput = inputs.addDropDownCommandInput(_DROPDOWN_INPUT_ID_CONSTRUCTION_PLANE, 'Construction Plane', adsk.core.DropDownStyles.TextListDropDownStyle) 677 | _constructionPlaneDropDownInput.listItems.add(_CONSTRUCTION_PLANE_XY, (_constructionPlane == _CONSTRUCTION_PLANE_XY)) 678 | _constructionPlaneDropDownInput.listItems.add(_CONSTRUCTION_PLANE_XZ, (_constructionPlane == _CONSTRUCTION_PLANE_XZ)) 679 | _constructionPlaneDropDownInput.listItems.add(_CONSTRUCTION_PLANE_YZ, (_constructionPlane == _CONSTRUCTION_PLANE_YZ)) 680 | _constructionPlaneDropDownInput.isVisible = not isSolidBodyStyle 681 | 682 | # Setup event handlers 683 | onExecute = MyCommandExecuteHandler() 684 | cmd.execute.add(onExecute) 685 | _handlers.append(onExecute) 686 | 687 | except: 688 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 689 | 690 | 691 | def run(context): 692 | try: 693 | global _app, _ui, _handlers 694 | _app = adsk.core.Application.get() 695 | _ui = _app.userInterface 696 | 697 | # Get the existing command definition or create it if it doesn't already exist. 698 | cmdDef = _ui.commandDefinitions.itemById(_IMPORT_CSV_POINTS_CMD_ID) 699 | if not cmdDef: 700 | cmdDef = _ui.commandDefinitions.addButtonDefinition(_IMPORT_CSV_POINTS_CMD_ID, 'Import CSV Points', 'Imports point values from a CSV file.', './resources') 701 | cmdDef.toolClipFilename = './resources/tooltip.png' 702 | 703 | # Connect to the command events. 704 | onCommandCreated = MyCommandCreatedHandler() 705 | cmdDef.commandCreated.add(onCommandCreated) 706 | _handlers.append(onCommandCreated) 707 | 708 | # Get the INSERT panel in the MODEL workspace. 709 | insertPanel = _ui.allToolbarPanels.itemById(_INSERT_PANEL_ID) 710 | 711 | # Add button to the panel 712 | btnControl = insertPanel.controls.itemById(_IMPORT_CSV_POINTS_CMD_ID) 713 | if not btnControl: 714 | btnControl = insertPanel.controls.addCommand(cmdDef) 715 | 716 | # Make the button available in the panel. 717 | btnControl.isPromotedByDefault = False 718 | btnControl.isPromoted = False 719 | 720 | if context['IsApplicationStartup'] is False: 721 | _ui.messageBox('The "Insert CSV Points" command has been\nadded to the INSERT panel dropdown.') 722 | except: 723 | if _ui: 724 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) 725 | 726 | 727 | def stop(context): 728 | try: 729 | # Delete controls and associated command definitions created by this add-ins 730 | insertPanel = _ui.allToolbarPanels.itemById(_INSERT_PANEL_ID) 731 | 732 | btnControl = insertPanel.controls.itemById(_IMPORT_CSV_POINTS_CMD_ID) 733 | if btnControl: 734 | btnControl.deleteMe() 735 | 736 | cmdDef = _ui.commandDefinitions.itemById(_IMPORT_CSV_POINTS_CMD_ID) 737 | if cmdDef: 738 | cmdDef.deleteMe() 739 | except: 740 | if _ui: 741 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Hans Kellner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #  Import CSV Points for Autodesk Fusion 360 2 | 3 | This is an [Autodesk Fusion 360](http://fusion360.autodesk.com/) add-in that imports a set of points from a CSV file and creates points/lines/splines in a sketch. 4 | 5 |  6 | 7 | The CSV file should contain comma separated coordinate values: 8 | 9 |
X,Y[,Z]10 | 11 | > The Z value is optional and will default to 0 if not present. Note that importing of 2D points is required if selecting a sketch or construction plane that is not on the XY plane. Otherwise, when 3D points are imported they are placed in modal space rather than relative to the sketch plane. 12 | 13 | Additionally, a blank line will indicate a break in a sequence of points. For example, when the CSV file contains points for multiple lines then each set should be separated by a blank line. Here is an example of defining the points for two lines: 14 | 15 |
16 | 1,1,1 17 | 2,2,2 18 | 3,3,3 19 | 20 | 2,8,0 21 | 4,6,1 22 | 6,4,0 23 | 8,2,1 24 |25 | 26 | The blank lines will only be recognized when creating lines or splines. Otherwise they will be ignored. 27 | 28 | ```NOTE: The script does not support UTF-8 encoded files. For example, Excel supports saving both UTF-8 and non-UTF-8 encoded CSV files. Choose the non-UTF-8.``` 29 | 30 | Here's the sketcher_vr_Simple.csv example: 31 | 32 |  33 | 34 | ## Installation 35 | 36 | Please see the most recent install instructions here: 37 | 38 | https://knowledge.autodesk.com/support/fusion-360/troubleshooting/caas/sfdcarticles/sfdcarticles/How-to-install-an-ADD-IN-and-Script-in-Fusion-360.html 39 | 40 | If you are installing manually, then please download the archive file (ZIP) from Github by clicking on the "Clone or download" button and then selecting "Download ZIP". 41 | 42 | Once you have the ZIP file, please follow the manual install instructions in the link above. 43 | 44 | Note, installing the add-in into the Fusion 360 Addins folder allows it to automatically be found and displayed in the add-ins list. 45 | 46 | ### Mac Add-Ins Folder 47 | 48 | ``` 49 | "$HOME/Library/Application Support/Autodesk/Autodesk Fusion 360/API/AddIns/" 50 | ``` 51 | 52 | ### Windows Add-Ins Folder 53 | 54 | ``` 55 | "C:\Users\%YOUR_USER_NAME%\AppData\Roaming\Autodesk\Autodesk Fusion 360\API\AddIns" 56 | ``` 57 | 58 | ### Manual Install 59 | 60 | 1. With your Finder or File Explorer window, locate the AddIns folder. 61 | 1. Create a folder within the AddIns folder with the same name as the add-in. In this case, "ImportCSVPoints". 62 | 1. Extract all of the add-in files from the (ZIP) archive and place them in this folder. 63 | 1. Now the add-in is ready for Fusion 360. Start Fusion 360. 64 | 1. Display the Scripts and Add-Ins dialog. The "ImportCSVPoints" add-in should be listed. 65 | 1. See the *Usage* section below for running and using. 66 | 67 | > As an alternative to the above installation location, you can just place the files in their own folder within a location of your choice. For example, in your Documents or Home folder. Doing this means the add-in will *not* automatically appear in the add-ins list. You will need to manually add it using the "+" button at the top of the list. 68 | 69 | ## Usage 70 | 71 | 1. Enter the Model environment 72 | 1. Run the "Import CSV Points" add-in from the Insert dropdown 73 | 74 |  75 | 76 | 1. The settings dialog will be shown 77 | 78 |  79 | 80 | - Units : Select the units of the CSV point values. 81 | - Style : Select one of the following styles to generate: 82 | * __Points__ : Create a sketch point for each point 83 | * __Lines__ : Create sketch lines connecting the points 84 | * __Fitted Splines__ : Create sketch splines connecting the points 85 | * __Solid Body__ : Experimental feature (see section below for information) 86 | - Sketch : Select a sketch to use or none. If no sketch is selected then a new sketch will be created on the construction plane selected (see below). 87 | - Construction Plane: 88 | * Enabled when no sketch or profile is selected. Select which construction plane for the new sketch created. 89 | 90 | 1. Click OK 91 | 1. A file dialog will be displayed. 92 | - Select the comma seperated value (CSV) file containing the points then click OK. 93 | 94 | ## Experimental Features 95 | 96 | ### Solid Body Style 97 | 98 | The "Solid Body" Style is an experimental feature and isn't guaranteed to work. 99 | 100 |  101 | 102 | When this style is selected, the dialog changes to allow selection of a single solid body. The selected solid body will be cloned for each point loaded from the CSV file. The locations loaded from the CSV file will be *relative* to the selected solid body. For example, a location of 0,0,0 will be at the same location of the selected body. A location of 5,5,0 will be offset 5 units in the XY direction. 103 | 104 | Here's selecting a sphere solid body. 105 | 106 |  107 | 108 | And the result of selecting the sphere and then the 'simple3D.csv' file. 109 | 110 |  111 | 112 | ### Patterns 113 | 114 | A CSV file may contain a "pattern" command on a line rather than a set of coordinates. See the sample files: 115 | 116 | * spiral.csv 117 | * spiralcube.csv 118 | 119 | If a CSV file contains a pattern command along with valid argument values, then a set of points will be generated and imported. For example, selecting the "Line" style and then the spiralcube.csv sample file will generate the following sketch. 120 | 121 |  122 | 123 | ### Pipes 124 | 125 | This is a little bit of a hack at the moment. But it's possible now to create pipes for lines/splines. To use this feature, include the "pipes" command in the CSV file. 126 | 127 | Usage 'Hollow' pipe: 128 | 129 |
pipes, OuterRadius, InnerRadius130 | 131 | Usage 'Solid' pipe: 132 | 133 |
pipes, OuterRadius134 | 135 | Arguments: 136 | 137 | - OuterRadius : Specifies the outer radius of the pipe 138 | - InnerRadius : (Optional) Specifies inner (hollow) radius or set to 0 or leave empty for a solid pipe 139 | 140 | See or try the sample CSV files whose filenames end with "_pipes.csv" for examples. 141 | 142 |  143 |  144 | 145 | ### Circles 146 | 147 | Drawing circles in 2D/3D 148 | 149 |
circle,x,y,radius150 |
circle,x,y,z,radius151 | 152 | ## Issues 153 | 154 | - The script does not support UTF-8 encoded files. For example, Excel supports saving both UTF-8 and non-UTF-8 encoded CSV files. Choose the non-UTF-8. 155 | - A large number of points can take a long time to import. The sample "sketcher_vr_BoxVaseFlower.csv" takes 35 seconds to import on my 2018 Mac Pro Laptop. 156 | - The OK button of the dialog will sometimes be disabled even though the settings are valid. The workaround is to force an update by selected a different construction plane or style then reselecting the original value. 157 | 158 | ## Credits 159 | 160 | - 2019.07.29 : [@caseymtimm](https://github.com/caseymtimm) pointed out feet -> cm conversion was incorrect. Submitted fix. 161 | - 2021.04.22 : [@HaikVasil](https://github.com/HaikVasil) provided fix for creating connecting lines. Also the suggestion to add Pipes support. 162 | -------------------------------------------------------------------------------- /images/filedialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/filedialog.png -------------------------------------------------------------------------------- /images/importcsvpoints-dialog-solidbody-sphere-simple3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/importcsvpoints-dialog-solidbody-sphere-simple3D.png -------------------------------------------------------------------------------- /images/importcsvpoints-dialog-solidbody-sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/importcsvpoints-dialog-solidbody-sphere.png -------------------------------------------------------------------------------- /images/importcsvpoints-dialog-solidbody.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/importcsvpoints-dialog-solidbody.png -------------------------------------------------------------------------------- /images/importcsvpoints-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/importcsvpoints-dialog.png -------------------------------------------------------------------------------- /images/insert-dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/insert-dropdown.png -------------------------------------------------------------------------------- /images/insert-tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/insert-tooltip.png -------------------------------------------------------------------------------- /images/simple2D_pipes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/simple2D_pipes.png -------------------------------------------------------------------------------- /images/sketcher_vr_BoxVaseFlowers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_BoxVaseFlowers.png -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_anim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_anim.gif -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_anim.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_anim.psd -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_back.png -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_front.png -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_left.png -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_pipes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_pipes.png -------------------------------------------------------------------------------- /images/sketcher_vr_Simple_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/sketcher_vr_Simple_right.png -------------------------------------------------------------------------------- /images/spiralcube_sketch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/images/spiralcube_sketch.png -------------------------------------------------------------------------------- /patterns.py: -------------------------------------------------------------------------------- 1 | #Author-Hans Kellner 2 | #Description-Functions for generating patterns. 3 | 4 | import adsk.core, adsk.fusion, traceback, math, random 5 | 6 | # Generate a sprial cube 7 | # @arg countPoints = 20 8 | # @arg angleDeg = 91 9 | # @arg lengthGrow = 1 10 | def generateSpiralCube(countPoints, angleDeg, lengthGrow): 11 | 12 | lineLength = 1 13 | points = [] 14 | 15 | dirVec = adsk.core.Vector3D.create(1,0,0) 16 | ptLast = adsk.core.Point3D.create(0,0,0) 17 | points.append(ptLast) 18 | 19 | mat = adsk.core.Matrix3D.create() 20 | 21 | for i in range(countPoints - 1): 22 | 23 | ptNext = adsk.core.Point3D.create(ptLast.x + (lineLength * dirVec.x), ptLast.y + (lineLength * dirVec.y), 0) 24 | points.append(ptNext) 25 | 26 | ptLast = ptNext 27 | 28 | mat.setToRotation(angleDeg/180*math.pi, adsk.core.Vector3D.create(0,0,1), adsk.core.Point3D.create(0,0,0)) 29 | dirVec.transformBy(mat) 30 | 31 | lineLength = lineLength + lengthGrow 32 | 33 | return [points] 34 | 35 | # Generate a sprial cube 36 | # @arg numArms = 10 37 | # @arg numPointsPerArm = 20 38 | # @arg armsOffset = 3 39 | # @arg rateExpansion = 3 40 | # @arg rateExpansion = 0.5 41 | def generateSpiral(numArms = 10, numPointsPerArm = 20, armsOffset = 3, rateExpansion = 5, zStep = 0): 42 | 43 | lines = [] 44 | 45 | for iArm in range(numArms): 46 | points = [] 47 | pZ = 0 48 | 49 | for iPt in range(numPointsPerArm): 50 | pX = rateExpansion * iPt * math.cos(iPt + (math.pi * iArm)) + (random.random() * armsOffset) 51 | pY = rateExpansion * iPt * math.sin(iPt + (math.pi * iArm)) + (random.random() * armsOffset) 52 | if zStep != 0: 53 | pZ += zStep * random.random() 54 | 55 | pt3D = adsk.core.Point3D.create(pX, pY, pZ) 56 | points.append(pt3D) 57 | 58 | lines.append(points) 59 | 60 | return lines 61 | 62 | -------------------------------------------------------------------------------- /pipe.py: -------------------------------------------------------------------------------- 1 | #Author-Hans Kellner 2 | #Description-Function for generating pipes along sketch lines. 3 | 4 | import adsk.core, adsk.fusion, traceback, math, random 5 | 6 | # Generate pipes that follow each specified sketch line 7 | # @arg rootComp 8 | # @arg sketchLines 9 | # @arg outerRadius 10 | # @arg innerRadius 11 | 12 | def createPipesOnLines(app, ui, sketchLines, outerDiam, innerDiam): 13 | 14 | design = app.activeProduct 15 | rootComp = design.rootComponent 16 | sketches = rootComp.sketches 17 | feats = rootComp.features 18 | 19 | for line in sketchLines: 20 | 21 | try: 22 | 23 | if False: 24 | 25 | # Command implementation 26 | # NOTE: This crashes Fusion. Possiby because the commands are executed within addin command? 27 | sels :adsk.core.Selections = ui.activeSelections 28 | sels.clear() 29 | sels.add(line) #path) 30 | 31 | txtCmds = [ 32 | u'Commands.Start PrimitivePipe', # show dialog 33 | u'Commands.SetDouble SWEEP_POP_ALONG 1.0', # input distance 34 | u'Commands.SetDouble SectionRadius 0.5', # input radius 35 | u'NuCommands.CommitCmd' # execute command 36 | ] 37 | 38 | for cmd in txtCmds: 39 | app.executeTextCommand(cmd) 40 | 41 | sels.clear() 42 | 43 | else: 44 | 45 | # create path 46 | path = feats.createPath(line, True) 47 | 48 | # create profile 49 | planes = rootComp.constructionPlanes 50 | planeInput = planes.createInput() 51 | planeInput.setByDistanceOnPath(path, adsk.core.ValueInput.createByReal(0)) 52 | plane = planes.add(planeInput) 53 | 54 | sketch = sketches.add(plane) 55 | 56 | center = sketch.modelToSketchSpace(plane.geometry.origin) 57 | 58 | circleOuter = sketch.sketchCurves.sketchCircles.addByCenterRadius(center, outerDiam) 59 | circleInner = None 60 | if innerDiam > 0: 61 | circleInner = sketch.sketchCurves.sketchCircles.addByCenterRadius(center, innerDiam) 62 | 63 | profileOuter = sketch.profiles[0] 64 | 65 | # create sweep for outer 66 | sweepFeats = feats.sweepFeatures 67 | sweepInputOuter = sweepFeats.createInput(profileOuter, path, adsk.fusion.FeatureOperations.JoinFeatureOperation) 68 | sweepInputOuter.orientation = adsk.fusion.SweepOrientationTypes.PerpendicularOrientationType 69 | sweepFeat = sweepFeats.add(sweepInputOuter) 70 | 71 | except: 72 | print("Unexpected error") 73 | -------------------------------------------------------------------------------- /resources/16x16-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/16x16-disabled.png -------------------------------------------------------------------------------- /resources/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/16x16.png -------------------------------------------------------------------------------- /resources/32x32-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/32x32-disabled.png -------------------------------------------------------------------------------- /resources/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/32x32.png -------------------------------------------------------------------------------- /resources/32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/32x32@2x.png -------------------------------------------------------------------------------- /resources/64x64.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/64x64.ai -------------------------------------------------------------------------------- /resources/tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/tooltip.png -------------------------------------------------------------------------------- /resources/tooltip.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanskellner/Fusion360ImportCSVPoints/246084a57094be5a473bf8d71e65c1a45269d703/resources/tooltip.psd -------------------------------------------------------------------------------- /samples/circles2D.csv: -------------------------------------------------------------------------------- 1 | circle,0,0,20 2 | circle,0,5,10 -------------------------------------------------------------------------------- /samples/simple2D.csv: -------------------------------------------------------------------------------- 1 | -1,-1 2 | -1,1 3 | 1,1 4 | 1,-1 5 | -1,-1 6 | 7 | 0,-6 8 | -6,6 9 | 6,6 10 | 0,-6 11 | 12 | -4,4 13 | -2,0 14 | 0,3 15 | 2,0 16 | 4,4 -------------------------------------------------------------------------------- /samples/simple2D_pipes.csv: -------------------------------------------------------------------------------- 1 | pipes, 0.3, 0.25 2 | 3 | -1,-1 4 | -1,1 5 | 1,1 6 | 1,-1 7 | -1,-1 8 | 9 | 0,-6 10 | -6,6 11 | 6,6 12 | 0,-6 13 | 14 | -4,4 15 | -2,0 16 | 0,3 17 | 2,0 18 | 4,4 -------------------------------------------------------------------------------- /samples/simple3D.csv: -------------------------------------------------------------------------------- 1 | 0,0,0 2 | 1,1,0 3 | 2,2,0 4 | 5 | 3,3,2 6 | 4,4,2 7 | 5,5,2 8 | 9 | 6,6,4 10 | 7,7,4 11 | 8,8,4 12 | 9,9,4 13 | -------------------------------------------------------------------------------- /samples/simple3D_pipes.csv: -------------------------------------------------------------------------------- 1 | pipes, 0.5, 0.4 2 | 3 | 0,0,0 4 | 1,1,0 5 | 2,2,0 6 | 7 | 3,3,2 8 | 4,4,2 9 | 5,5,2 10 | 11 | 6,6,4 12 | 7,7,4 13 | 8,8,4 14 | 9,9,4 15 | -------------------------------------------------------------------------------- /samples/sketcher_vr_Simple.csv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0.52797639369965,-0.31674987077713,1.0419343709946 4 | 0.52900892496109,-0.31308296322823,1.0427441596985 5 | 0.53000527620316,-0.30990162491798,1.0433470010757 6 | 0.5334644317627,-0.30599305033684,1.0450683832169 7 | 0.53509259223938,-0.30219697952271,1.0462117195129 8 | 0.53783130645752,-0.298997849226,1.0479712486267 9 | 0.54179441928864,-0.29618856310844,1.0512372255325 10 | 0.54522210359573,-0.29278957843781,1.0548485517502 11 | 0.54899972677231,-0.28942283987999,1.0589282512665 12 | 0.55334627628326,-0.2869668006897,1.0638929605484 13 | 0.55688554048538,-0.28407406806946,1.0680305957794 14 | 0.5606524348259,-0.28159552812576,1.0725754499435 15 | 0.56466794013977,-0.28010407090187,1.0780147314072 16 | 0.56843489408493,-0.27795815467834,1.0833926200867 17 | 0.57208913564682,-0.27605065703392,1.0892558097839 18 | 0.5763093829155,-0.27522167563438,1.0959175825119 19 | 0.57973182201385,-0.27481198310852,1.1032643318176 20 | 0.58301961421967,-0.27349776029587,1.1092323064804 21 | 0.58690774440765,-0.2750691473484,1.1182789802551 22 | 0.58961230516434,-0.27550548315048,1.1261976957321 23 | 0.59332269430161,-0.27759569883347,1.1355965137482 24 | 0.59570187330246,-0.27863851189613,1.1441833972931 25 | 0.59744769334793,-0.28106090426445,1.153368473053 26 | 0.59878915548325,-0.28407663106918,1.1627277135849 27 | 0.60118639469147,-0.28804457187653,1.1730834245682 28 | 0.60174965858459,-0.291718095541,1.1827785968781 29 | 0.60183244943619,-0.29537090659142,1.1923866271973 30 | 0.60270190238953,-0.30028375983238,1.2036163806915 31 | 0.60207796096802,-0.30395957827568,1.2127232551575 32 | 0.60096859931946,-0.30775153636932,1.2213668823242 33 | 0.6009863615036,-0.31345212459564,1.2310087680817 34 | 0.5997040271759,-0.31739801168442,1.2396557331085 35 | 0.59762227535248,-0.32173192501068,1.2473386526108 36 | 0.59682124853134,-0.32747292518616,1.255964756012 37 | 0.59407156705856,-0.33220908045769,1.2630997896194 38 | 0.59948778152466,-0.3453813791275,1.2774242162704 39 | 0.59582960605621,-0.35061502456665,1.2830164432526 40 | 0.5928567647934,-0.35539767146111,1.2892659902573 41 | 0.59005349874496,-0.36016047000885,1.2953636646271 42 | 0.58576345443726,-0.36490455269814,1.2991256713867 43 | 0.58202278614044,-0.36961805820465,1.3036580085754 44 | 0.57815408706665,-0.37450817227364,1.306799530983 45 | 0.5739506483078,-0.37942564487457,1.3097325563431 46 | 0.5693501830101,-0.38481247425079,1.3106695413589 47 | 0.56494545936584,-0.38970679044724,1.3123499155045 48 | 0.56087625026703,-0.39460736513138,1.312797665596 49 | 0.5562795996666,-0.39975786209106,1.31281042099 50 | 0.55437290668488,-0.40699845552444,1.3150458335876 51 | 0.54906588792801,-0.41213485598564,1.3123786449432 52 | 0.54378837347031,-0.41694059967995,1.3099799156189 53 | 0.53871059417725,-0.42215153574944,1.3079760074615 54 | 0.53348016738892,-0.42741703987122,1.3035025596619 55 | 0.52816551923752,-0.43205958604813,1.2986114025116 56 | 0.52295112609863,-0.43654772639275,1.2941552400589 57 | 0.51808726787567,-0.44050535559654,1.2877594232559 58 | 0.51329910755157,-0.44336050748825,1.2809695005417 59 | 0.50858289003372,-0.44598791003227,1.2740707397461 60 | 0.50418090820313,-0.44832968711853,1.2668615579605 61 | 0.49994340538979,-0.44932729005814,1.2600299119949 62 | 0.49611029028893,-0.44886055588722,1.2529788017273 63 | 0.49221527576447,-0.44868862628937,1.2458579540253 64 | 0.48882779479027,-0.44684171676636,1.2377097606659 65 | 0.48567181825638,-0.44451177120209,1.2293914556503 66 | 0.48255923390388,-0.442357391119,1.2218871116638 67 | 0.48183235526085,-0.43712836503983,1.214882850647 68 | 0.48073127865791,-0.43295389413834,1.2081553936005 69 | 0.48105227947235,-0.42701959609985,1.2020086050034 70 | 0.48142102360725,-0.4218510389328,1.1957802772522 71 | 0.48144921660423,-0.41765573620796,1.1898684501648 72 | 0.48191741108894,-0.41244694590569,1.185010433197 73 | 0.48230868577957,-0.40801113843918,1.180401802063 74 | 0.48302432894707,-0.40328726172447,1.1759850978851 75 | 0.48392948508263,-0.39816603064537,1.1721884012222 76 | 0.48564198613167,-0.39281430840492,1.1690894365311 77 | 0.48779222369194,-0.38705903291702,1.1660567522049 78 | 0.49072068929672,-0.38011029362679,1.1647062301636 79 | 0.49440741539001,-0.37332639098167,1.1633871793747 80 | 0.4979804456234,-0.36701348423958,1.1617716550827 81 | 0.50284266471863,-0.35992088913918,1.1617841720581 82 | 0.50723820924759,-0.35320129990578,1.1607865095139 83 | 0.51267379522324,-0.34637171030045,1.1609556674957 84 | 0.51841962337494,-0.33902037143707,1.1616376638412 85 | 0.52456510066986,-0.33175531029701,1.1624429225922 86 | 0.53064858913422,-0.32479441165924,1.1631405353546 87 | 0.53712904453278,-0.31727787852287,1.164478302002 88 | 0.54407405853271,-0.30959716439247,1.165803194046 89 | 0.55141806602478,-0.30163684487343,1.1677844524384 90 | 0.5586599111557,-0.2928255200386,1.1704201698303 91 | 0.5658832192421,-0.28435641527176,1.1728106737137 92 | 0.57329857349396,-0.27517509460449,1.1758970022202 93 | 0.58033615350723,-0.26543760299683,1.1792639493942 94 | 0.58748733997345,-0.25562909245491,1.1824028491974 95 | 0.59412968158722,-0.24611127376556,1.1854264736176 96 | 0.60039561986923,-0.23537288606167,1.1887623071671 97 | 0.60652720928192,-0.22533167898655,1.1914207935333 98 | 0.61184865236282,-0.21514976024628,1.1935150623322 99 | 0.61675584316254,-0.20433589816093,1.1952210664749 100 | 0.62120246887207,-0.19368670880795,1.1963422298431 101 | 0.6256428360939,-0.18303643167019,1.1975469589233 102 | 103 | 104 | 105 | 0.62884336709976,-0.17251029610634,1.1980373859406 106 | 0.63111770153046,-0.16229169070721,1.1980061531067 107 | 0.63374841213226,-0.15260228514671,1.1981844902039 108 | 0.63382142782211,-0.14385388791561,1.1967537403107 109 | 0.63570386171341,-0.13633027672768,1.1969534158707 110 | 0.63517290353775,-0.12948709726334,1.1956769227982 111 | 0.63424378633499,-0.12237057089806,1.1935274600983 112 | 0.63296788930893,-0.11575815081596,1.1915444135666 113 | 0.63117468357086,-0.10892076045275,1.1894903182983 114 | 0.62828081846237,-0.1029988899827,1.186439871788 115 | 0.62520945072174,-0.097124308347702,1.1838718652725 116 | 0.62076783180237,-0.092006117105484,1.1807897090912 117 | 0.61611545085907,-0.087723910808563,1.1769219636917 118 | 0.61157548427582,-0.082945600152016,1.1734035015106 119 | 0.6065645813942,-0.080067418515682,1.1698468923569 120 | 0.60030299425125,-0.077351607382298,1.1651163101196 121 | 0.59361207485199,-0.074188597500324,1.1603788137436 122 | 0.58705353736877,-0.071845084428787,1.1565951108932 123 | 0.5790701508522,-0.071767538785934,1.1516820192337 124 | 0.57195919752121,-0.070434920489788,1.1472022533417 125 | 0.56447976827621,-0.071413673460484,1.1432098150253 126 | 0.5563856959343,-0.072453320026398,1.1384116411209 127 | 0.54839473962784,-0.073835097253323,1.1336970329285 128 | 0.54034733772278,-0.075091078877449,1.1289403438568 129 | 0.53178882598877,-0.077942810952663,1.1239913702011 130 | 0.52317631244659,-0.081768907606602,1.1191087961197 131 | 0.51483821868896,-0.08630109578371,1.1143239736557 132 | 0.50642424821854,-0.090439260005951,1.1100213527679 133 | 0.49802154302597,-0.096340380609035,1.1057984828949 134 | 0.49008795619011,-0.10247732698917,1.1018408536911 135 | 0.48174139857292,-0.10948471724987,1.0981794595718 136 | 0.47334799170494,-0.11709782481194,1.0948075056076 137 | 0.46502822637558,-0.12421064078808,1.0915883779526 138 | 0.4567768573761,-0.1323037147522,1.0892876386642 139 | 0.44881048798561,-0.14069963991642,1.0873365402222 140 | 0.44118595123291,-0.14952640235424,1.0858074426651 141 | 0.43369022011757,-0.15878528356552,1.0848625898361 142 | 0.42633712291718,-0.16794237494469,1.0835404396057 143 | 0.4198123216629,-0.17786622047424,1.083202958107 144 | 0.41369491815567,-0.18682855367661,1.0840229988098 145 | 0.40760570764542,-0.19538821280003,1.0845712423325 146 | 0.40275663137436,-0.20348200201988,1.08658182621 147 | 0.39845454692841,-0.21110381186008,1.0903940200806 148 | 0.39356189966202,-0.21896368265152,1.0931618213654 149 | 0.38991636037827,-0.22590094804764,1.0976721048355 150 | 0.38582348823547,-0.23167583346367,1.1031458377838 151 | 0.38183784484863,-0.23792505264282,1.1078577041626 152 | 0.37902921438217,-0.24263426661491,1.1143162250519 153 | 0.3750461935997,-0.24713242053986,1.1200432777405 154 | 0.37240579724312,-0.25142508745193,1.1258054971695 155 | 0.3699049949646,-0.25583764910698,1.1312954425812 156 | 0.36881673336029,-0.25819209218025,1.1375017166138 157 | 0.3671917617321,-0.26031738519669,1.1439300775528 158 | 0.36657717823982,-0.26263192296028,1.1503239870071 159 | 0.36568781733513,-0.26485785841942,1.1564513444901 160 | 0.37021282315254,-0.26952394843102,1.1666616201401 161 | 0.37087261676788,-0.26971653103828,1.1734592914581 162 | 0.37185782194138,-0.2690044939518,1.1807118654251 163 | 0.37394827604294,-0.26769757270813,1.1877549886703 164 | 0.3750938475132,-0.26720026135445,1.1942633390427 165 | 0.37796437740326,-0.26335248351097,1.201918721199 166 | 0.38057321310043,-0.26099172234535,1.2088547945023 167 | 0.38475799560547,-0.25565111637115,1.2154800891876 168 | 0.38775587081909,-0.25119721889496,1.2222570180893 169 | 0.3919517993927,-0.24613597989082,1.2285474538803 170 | 0.39668792486191,-0.24009341001511,1.2343193292618 171 | 0.40138012170792,-0.23391284048557,1.2402429580688 172 | 0.40563517808914,-0.22829100489616,1.2460815906525 173 | 0.41086944937706,-0.22157590091228,1.2516559362411 174 | 0.41572138667107,-0.21486921608448,1.257496714592 175 | 0.42112043499947,-0.20775136351585,1.2631169557571 176 | 0.42668226361275,-0.20041127502918,1.2686768770218 177 | 0.43168851733208,-0.19367448985577,1.2745530605316 178 | 0.4370351433754,-0.18663682043552,1.2800981998444 179 | 0.44342693686485,-0.17959371209145,1.2856419086456 180 | 0.44900760054588,-0.17302204668522,1.2915514707565 181 | 0.45530080795288,-0.16684992611408,1.2975367307663 182 | 0.46187311410904,-0.1611276268959,1.3038463592529 183 | 0.46780946850777,-0.15567865967751,1.3101243972778 184 | 0.47399160265923,-0.15021988749504,1.3165043592453 185 | 0.48011985421181,-0.14552256464958,1.3227798938751 186 | 0.48622307181358,-0.14077790081501,1.329238653183 187 | 0.4921789765358,-0.13614550232887,1.3354551792145 188 | 0.49761241674423,-0.13209575414658,1.3417420387268 189 | 0.50343418121338,-0.12818844616413,1.3480852842331 190 | 0.50927931070328,-0.12553678452969,1.3549022674561 191 | 0.51499402523041,-0.12456148862839,1.3621615171432 192 | 0.52066373825073,-0.1235304325819,1.3692765235901 193 | 0.52628242969513,-0.12230488657951,1.3762296438217 194 | 0.53157180547714,-0.12263414263725,1.3832358121872 195 | 0.53689754009247,-0.12325820326805,1.390322804451 196 | 0.54202163219452,-0.12469261884689,1.397231221199 197 | 0.54730224609375,-0.12588700652122,1.4041028022766 198 | 0.55209898948669,-0.12869265675545,1.4108097553253 199 | 0.5565305352211,-0.13201659917831,1.4175647497177 200 | 0.56068599224091,-0.13619661331177,1.4240453243256 201 | 0.56424671411514,-0.14063429832458,1.4305158853531 202 | 0.56780850887299,-0.14474917948246,1.4370113611221 203 | 0.57022172212601,-0.15058082342148,1.4431657791138 204 | 0.5729004740715,-0.15547776222229,1.4493339061737 205 | 206 | 0.57513481378555,-0.16076582670212,1.4556149244308 207 | 0.57694202661514,-0.16736747324467,1.4613265991211 208 | 0.57775521278381,-0.17446433007717,1.4671412706375 209 | 0.57733231782913,-0.18226879835129,1.4728746414185 210 | 0.57854217290878,-0.18857952952385,1.4788517951965 211 | 0.57671463489532,-0.19704462587833,1.4848109483719 212 | 0.57561779022217,-0.20473974943161,1.4906942844391 213 | 0.57341063022614,-0.21325780451298,1.496374130249 214 | 0.57060635089874,-0.22162057459354,1.5013734102249 215 | 0.56726205348969,-0.22984355688095,1.5058609247208 216 | 0.56352305412292,-0.23834958672523,1.5101939439774 217 | 0.55975705385208,-0.24660275876522,1.5145065784454 218 | 0.55451858043671,-0.25567570328712,1.5178039073944 219 | 0.55052042007446,-0.26371046900749,1.5215618610382 220 | 0.54397433996201,-0.2717277109623,1.5230094194412 221 | 0.53782337903976,-0.28026416897774,1.5249882936478 222 | 0.53108775615692,-0.28901648521423,1.5262273550034 223 | 0.52389448881149,-0.29722627997398,1.5272208452225 224 | 0.51635760068893,-0.30543828010559,1.5277760028839 225 | 0.50896817445755,-0.31365966796875,1.5282220840454 226 | 0.5012389421463,-0.3217887878418,1.5272297859192 227 | 0.4934675693512,-0.32962599396706,1.5262100696564 228 | 0.48571366071701,-0.33721598982811,1.5238634347916 229 | 0.47765576839447,-0.34472423791885,1.5210909843445 230 | 0.46984657645226,-0.35184335708618,1.5184707641602 231 | 0.46197211742401,-0.35827255249023,1.5135613679886 232 | 0.45362284779549,-0.36474749445915,1.5091987848282 233 | 0.44528084993362,-0.37123334407806,1.5049675703049 234 | 0.43744856119156,-0.37721872329712,1.4993691444397 235 | 0.42920309305191,-0.38306578993797,1.4945809841156 236 | 0.42149007320404,-0.38686570525169,1.4883190393448 237 | 0.41418474912643,-0.39101380109787,1.483074426651 238 | 0.40682142972946,-0.39539739489555,1.4773528575897 239 | 0.40000179409981,-0.39923942089081,1.47125685215 240 | 0.39372915029526,-0.40294343233109,1.4652274847031 241 | 0.38860189914703,-0.4057345688343,1.4589229822159 242 | 0.38289660215378,-0.4084320962429,1.4525836706161 243 | 0.37913829088211,-0.40994009375572,1.4461611509323 244 | 0.37536728382111,-0.41158780455589,1.439957857132 245 | 0.37197723984718,-0.41225302219391,1.4338310956955 246 | 0.36918050050735,-0.41307416558266,1.4277483224869 247 | 0.36798173189163,-0.41206920146942,1.4228919744492 248 | 0.36697053909302,-0.41075873374939,1.4180583953857 249 | 0.36633601784706,-0.40932735800743,1.4132393598557 250 | 0.36574637889862,-0.40792673826218,1.4090774059296 251 | 0.36773970723152,-0.4040612578392,1.4064053297043 252 | 0.36933156847954,-0.40000048279762,1.403754234314 253 | 0.37046581506729,-0.39717996120453,1.4005589485168 254 | 0.37287196516991,-0.39248377084732,1.3972375392914 255 | 0.375981092453,-0.38768383860588,1.3945951461792 256 | 0.37970721721649,-0.38295498490334,1.3919885158539 257 | 0.38279417157173,-0.37768885493279,1.3890929222107 258 | 0.38754081726074,-0.37162065505981,1.3872482776642 259 | 0.39250952005386,-0.36565986275673,1.3853591680527 260 | 0.39797189831734,-0.35911318659782,1.3828682899475 261 | 0.40337711572647,-0.35297992825508,1.3803161382675 262 | 0.41005536913872,-0.34588947892189,1.3776608705521 263 | 0.41621118783951,-0.3386395573616,1.3746116161346 264 | 0.42395153641701,-0.33094951510429,1.3714470863342 265 | 0.43196919560432,-0.32316792011261,1.3683271408081 266 | 0.43862119317055,-0.31601032614708,1.3650261163712 267 | 0.44595387578011,-0.30948725342751,1.3615198135376 268 | 0.45337575674057,-0.30291354656219,1.357904791832 269 | 0.46064308285713,-0.29583847522736,1.354033946991 270 | 0.46808397769928,-0.28901743888855,1.3504750728607 271 | 0.47538632154465,-0.28243547677994,1.3467725515366 272 | 0.4823704957962,-0.27605155110359,1.3430912494659 273 | 0.48982998728752,-0.26940149068832,1.3391819000244 274 | 0.49741354584694,-0.26271516084671,1.3348729610443 275 | 0.50459289550781,-0.25634771585464,1.33023416996 276 | 0.51203888654709,-0.2502963244915,1.3253902196884 277 | 0.51917672157288,-0.24431936442852,1.3208774328232 278 | 0.52623867988586,-0.23877297341824,1.3161036968231 279 | 0.53299504518509,-0.23315393924713,1.311198592186 280 | 0.5396094918251,-0.22767451405525,1.3057050704956 281 | 0.5459315776825,-0.22185899317265,1.3004437685013 282 | 0.55129796266556,-0.21615880727768,1.2943187952042 283 | 0.55685466527939,-0.21042415499687,1.2886875867844 284 | 0.56135076284409,-0.2044911980629,1.2837388515472 285 | 0.56501829624176,-0.19879803061485,1.2792247533798 286 | 0.56871294975281,-0.19300247728825,1.2748832702637 287 | 0.57142001390457,-0.18799661099911,1.2703988552094 288 | 0.5732034444809,-0.18324244022369,1.2659822702408 289 | 0.57434499263763,-0.1786430478096,1.2617398500443 290 | 0.57546770572662,-0.17394252121449,1.2576621770859 291 | 0.57510811090469,-0.16901478171349,1.2543264627457 292 | 0.57412397861481,-0.16460433602333,1.2510182857513 293 | 0.5724783539772,-0.16054034233093,1.2479070425034 294 | 0.5704283118248,-0.15643087029457,1.2451835870743 295 | 0.56855112314224,-0.15252327919006,1.2422292232513 296 | 0.56564193964005,-0.14897009730339,1.2397639751434 297 | 0.56190943717957,-0.14538936316967,1.2377727031708 298 | 0.55549013614655,-0.13946701586246,1.2333935499191 299 | 0.55325412750244,-0.13902744650841,1.2331416606903 300 | 0.54842418432236,-0.13681800663471,1.2315142154694 301 | 0.54385125637054,-0.13449375331402,1.229682803154 302 | 0.53881299495697,-0.13343098759651,1.2287931442261 303 | 0.53301227092743,-0.13210111856461,1.228059887886 304 | 0.52694875001907,-0.13097663223743,1.2278174161911 305 | 0.52207434177399,-0.129953160882,1.2275046110153 306 | 0.5155816078186,-0.1288206577301,1.227792263031 307 | 0.50902998447418,-0.1277939081192,1.2279583215714 308 | 0.50269460678101,-0.12719543278217,1.2287003993988 309 | 0.4956588447094,-0.12647467851639,1.2294085025787 310 | 0.48857137560844,-0.12603850662708,1.2301154136658 311 | 0.48180013895035,-0.12549406290054,1.2306308746338 312 | 0.47444823384285,-0.12531967461109,1.2316973209381 313 | 0.46736699342728,-0.1257596462965,1.2323304414749 314 | 0.46051141619682,-0.12612679600716,1.2331569194794 315 | 0.45349705219269,-0.12625841796398,1.234791636467 316 | 0.44667336344719,-0.12666949629784,1.2361356019974 317 | 0.43987247347832,-0.12751369178295,1.2376997470856 318 | 0.43296578526497,-0.1280193477869,1.239431977272 319 | 0.42603915929794,-0.12894958257675,1.2413136959076 320 | 0.41900387406349,-0.12991693615913,1.2433590888977 321 | 0.41207960247993,-0.13095417618752,1.2455879449844 322 | 0.40521395206451,-0.13224630057812,1.2477599382401 323 | 0.39832749962807,-0.13374491035938,1.2496404647827 324 | 0.39211809635162,-0.13612258434296,1.2511167526245 325 | 0.38588413596153,-0.13841152191162,1.2523957490921 326 | 0.3801786005497,-0.14165148139,1.2536696195602 327 | 0.37455001473427,-0.14522942900658,1.2555985450745 328 | 0.37216109037399,-0.15181535482407,1.2604193687439 329 | 0.36654663085938,-0.15535278618336,1.2629170417786 330 | 0.36134299635887,-0.15907806158066,1.265533208847 331 | 0.35689759254456,-0.16336123645306,1.267187833786 332 | 0.35307258367538,-0.16787211596966,1.2687366008759 333 | 0.34977412223816,-0.17222039401531,1.2709327936172 334 | 0.34625402092934,-0.1765713095665,1.2731641530991 335 | 0.34372460842133,-0.18164679408073,1.2760370969772 336 | 0.34169220924377,-0.18722455203533,1.2788743972778 337 | 0.33995690941811,-0.19250282645226,1.2817587852478 338 | 0.33792081475258,-0.19726057350636,1.2843624353409 339 | 0.33658307790756,-0.20191295444965,1.2873603105545 340 | 0.33562231063843,-0.20667570829391,1.2896949052811 341 | 0.33519488573074,-0.21152514219284,1.291934132576 342 | 0.33504372835159,-0.21641698479652,1.2943164110184 343 | 0.33484718203545,-0.22087505459785,1.2963968515396 344 | 0.33594483137131,-0.22493682801723,1.2986744642258 345 | 0.33723905682564,-0.2287223637104,1.3011051416397 346 | 0.33877551555634,-0.23238725960255,1.3030704259872 347 | 0.34115406870842,-0.23578174412251,1.3045547008514 348 | 0.34332272410393,-0.23940694332123,1.3057625293732 349 | 0.34562474489212,-0.24278454482555,1.3062962293625 350 | 0.34785643219948,-0.24650567770004,1.3068910837173 351 | 0.35040253400803,-0.25080260634422,1.3068755865097 352 | 0.35267129540443,-0.25470900535583,1.3067674636841 353 | 0.35565686225891,-0.25894257426262,1.3064702749252 354 | 0.3587754368782,-0.26331874728203,1.305755853653 355 | 0.36205065250397,-0.26745009422302,1.3049088716507 356 | 0.36525845527649,-0.27127912640572,1.3041063547134 357 | 358 | 0.36900272965431,-0.27502888441086,1.3027515411377 359 | 0.37234684824944,-0.27910235524178,1.3019518852234 360 | 0.3757728934288,-0.28312343358994,1.3003981113434 361 | 0.37933576107025,-0.28743815422058,1.2983059883118 362 | 0.38268640637398,-0.29185232520103,1.2961956262589 363 | 0.38595759868622,-0.29674082994461,1.294560790062 364 | 0.38902109861374,-0.30160665512085,1.2934353351593 365 | 0.39208179712296,-0.30636739730835,1.2925812005997 366 | 0.39483886957169,-0.31118234992027,1.2915785312653 367 | 0.39781919121742,-0.31528377532959,1.2904382944107 368 | 0.40132719278336,-0.31905061006546,1.2891129255295 369 | 0.40455573797226,-0.32269793748856,1.2879060506821 370 | 0.40787270665169,-0.32558310031891,1.2869817018509 371 | 0.41102123260498,-0.32875749468803,1.2861088514328 372 | 0.41383016109467,-0.33190128207207,1.2851686477661 373 | 0.41657614707947,-0.33506268262863,1.2841092348099 374 | 0.41844287514687,-0.33826321363449,1.2829381227493 375 | 0.42029583454132,-0.3417851626873,1.2820633649826 376 | 0.42124861478806,-0.34528717398643,1.2819508314133 377 | 0.42202237248421,-0.3486750125885,1.2819026708603 378 | 0.42109400033951,-0.35201844573021,1.2821259498596 379 | 0.4209375679493,-0.35517072677612,1.2818132638931 380 | 0.42022681236267,-0.35842248797417,1.2814370393753 381 | 0.4184817969799,-0.36127510666847,1.2813489437103 382 | 0.41637125611305,-0.36415418982506,1.2815104722977 383 | 0.41359123587608,-0.36730122566223,1.2824087142944 384 | 0.40997785329819,-0.36955294013023,1.2837618589401 385 | -------------------------------------------------------------------------------- /samples/sketcher_vr_Simple_pipes.csv: -------------------------------------------------------------------------------- 1 | pipes, 0.02, 0.015 2 | 3 | 0.52797639369965,-0.31674987077713,1.0419343709946 4 | 0.5334644317627,-0.30599305033684,1.0450683832169 5 | 0.54179441928864,-0.29618856310844,1.0512372255325 6 | 0.55334627628326,-0.2869668006897,1.0638929605484 7 | 0.56466794013977,-0.28010407090187,1.0780147314072 8 | 0.5763093829155,-0.27522167563438,1.0959175825119 9 | 0.58690774440765,-0.2750691473484,1.1182789802551 10 | 0.59570187330246,-0.27863851189613,1.1441833972931 11 | 0.59744769334793,-0.28106090426445,1.153368473053 12 | 0.60174965858459,-0.291718095541,1.1827785968781 13 | 0.60207796096802,-0.30395957827568,1.2127232551575 14 | 0.5997040271759,-0.31739801168442,1.2396557331085 15 | 0.59407156705856,-0.33220908045769,1.2630997896194 16 | 0.5928567647934,-0.35539767146111,1.2892659902573 17 | 0.58202278614044,-0.36961805820465,1.3036580085754 18 | 0.5693501830101,-0.38481247425079,1.3106695413589 19 | 0.5562795996666,-0.39975786209106,1.31281042099 20 | 0.54378837347031,-0.41694059967995,1.3099799156189 21 | 0.52816551923752,-0.43205958604813,1.2986114025116 22 | 0.51329910755157,-0.44336050748825,1.2809695005417 23 | 0.49994340538979,-0.44932729005814,1.2600299119949 24 | 0.48882779479027,-0.44684171676636,1.2377097606659 25 | 0.48183235526085,-0.43712836503983,1.214882850647 26 | 0.48142102360725,-0.4218510389328,1.1957802772522 27 | 0.48230868577957,-0.40801113843918,1.180401802063 28 | 0.48564198613167,-0.39281430840492,1.1690894365311 29 | 0.49440741539001,-0.37332639098167,1.1633871793747 30 | 0.50723820924759,-0.35320129990578,1.1607865095139 31 | 0.52456510066986,-0.33175531029701,1.1624429225922 32 | 0.54407405853271,-0.30959716439247,1.165803194046 33 | 0.5658832192421,-0.28435641527176,1.1728106737137 34 | 0.58748733997345,-0.25562909245491,1.1824028491974 35 | 0.60652720928192,-0.22533167898655,1.1914207935333 36 | 0.6256428360939,-0.18303643167019,1.1975469589233 37 | 0.62884336709976,-0.17251029610634,1.1980373859406 38 | 0.63382142782211,-0.14385388791561,1.1967537403107 39 | 0.63424378633499,-0.12237057089806,1.1935274600983 40 | 0.62828081846237,-0.1029988899827,1.186439871788 41 | 0.61611545085907,-0.087723910808563,1.1769219636917 42 | 0.60030299425125,-0.077351607382298,1.1651163101196 43 | 0.5790701508522,-0.071767538785934,1.1516820192337 44 | 0.5563856959343,-0.072453320026398,1.1384116411209 45 | 0.53178882598877,-0.077942810952663,1.1239913702011 46 | 0.50642424821854,-0.090439260005951,1.1100213527679 47 | 0.48174139857292,-0.10948471724987,1.0981794595718 48 | 0.4567768573761,-0.1323037147522,1.0892876386642 49 | 0.43369022011757,-0.15878528356552,1.0848625898361 50 | 0.41369491815567,-0.18682855367661,1.0840229988098 51 | 0.39845454692841,-0.21110381186008,1.0903940200806 52 | 0.38582348823547,-0.23167583346367,1.1031458377838 53 | 0.3750461935997,-0.24713242053986,1.1200432777405 54 | 0.36881673336029,-0.25819209218025,1.1375017166138 55 | 0.36568781733513,-0.26485785841942,1.1564513444901 56 | 0.37185782194138,-0.2690044939518,1.1807118654251 57 | 0.37796437740326,-0.26335248351097,1.201918721199 58 | 0.38775587081909,-0.25119721889496,1.2222570180893 59 | 0.40138012170792,-0.23391284048557,1.2402429580688 60 | 0.41572138667107,-0.21486921608448,1.257496714592 61 | 0.43168851733208,-0.19367448985577,1.2745530605316 62 | 0.44900760054588,-0.17302204668522,1.2915514707565 63 | 0.46780946850777,-0.15567865967751,1.3101243972778 64 | 0.48622307181358,-0.14077790081501,1.329238653183 65 | 0.50343418121338,-0.12818844616413,1.3480852842331 66 | 0.52066373825073,-0.1235304325819,1.3692765235901 67 | 0.53689754009247,-0.12325820326805,1.390322804451 68 | 0.55209898948669,-0.12869265675545,1.4108097553253 69 | 0.56424671411514,-0.14063429832458,1.4305158853531 70 | 0.5729004740715,-0.15547776222229,1.4493339061737 71 | -------------------------------------------------------------------------------- /samples/sketcher_vr_Simple_pipes_solid.csv: -------------------------------------------------------------------------------- 1 | pipes, 0.02 2 | 3 | 0.52797639369965,-0.31674987077713,1.0419343709946 4 | 0.5334644317627,-0.30599305033684,1.0450683832169 5 | 0.54179441928864,-0.29618856310844,1.0512372255325 6 | 0.55334627628326,-0.2869668006897,1.0638929605484 7 | 0.56466794013977,-0.28010407090187,1.0780147314072 8 | 0.5763093829155,-0.27522167563438,1.0959175825119 9 | 0.58690774440765,-0.2750691473484,1.1182789802551 10 | 0.59570187330246,-0.27863851189613,1.1441833972931 11 | 0.59744769334793,-0.28106090426445,1.153368473053 12 | 0.60174965858459,-0.291718095541,1.1827785968781 13 | 0.60207796096802,-0.30395957827568,1.2127232551575 14 | 0.5997040271759,-0.31739801168442,1.2396557331085 15 | 0.59407156705856,-0.33220908045769,1.2630997896194 16 | 0.5928567647934,-0.35539767146111,1.2892659902573 17 | 0.58202278614044,-0.36961805820465,1.3036580085754 18 | 0.5693501830101,-0.38481247425079,1.3106695413589 19 | 0.5562795996666,-0.39975786209106,1.31281042099 20 | 0.54378837347031,-0.41694059967995,1.3099799156189 21 | 0.52816551923752,-0.43205958604813,1.2986114025116 22 | 0.51329910755157,-0.44336050748825,1.2809695005417 23 | 0.49994340538979,-0.44932729005814,1.2600299119949 24 | 0.48882779479027,-0.44684171676636,1.2377097606659 25 | 0.48183235526085,-0.43712836503983,1.214882850647 26 | 0.48142102360725,-0.4218510389328,1.1957802772522 27 | 0.48230868577957,-0.40801113843918,1.180401802063 28 | 0.48564198613167,-0.39281430840492,1.1690894365311 29 | 0.49440741539001,-0.37332639098167,1.1633871793747 30 | 0.50723820924759,-0.35320129990578,1.1607865095139 31 | 0.52456510066986,-0.33175531029701,1.1624429225922 32 | 0.54407405853271,-0.30959716439247,1.165803194046 33 | 0.5658832192421,-0.28435641527176,1.1728106737137 34 | 0.58748733997345,-0.25562909245491,1.1824028491974 35 | 0.60652720928192,-0.22533167898655,1.1914207935333 36 | 0.6256428360939,-0.18303643167019,1.1975469589233 37 | 0.62884336709976,-0.17251029610634,1.1980373859406 38 | 0.63382142782211,-0.14385388791561,1.1967537403107 39 | 0.63424378633499,-0.12237057089806,1.1935274600983 40 | 0.62828081846237,-0.1029988899827,1.186439871788 41 | 0.61611545085907,-0.087723910808563,1.1769219636917 42 | 0.60030299425125,-0.077351607382298,1.1651163101196 43 | 0.5790701508522,-0.071767538785934,1.1516820192337 44 | 0.5563856959343,-0.072453320026398,1.1384116411209 45 | 0.53178882598877,-0.077942810952663,1.1239913702011 46 | 0.50642424821854,-0.090439260005951,1.1100213527679 47 | 0.48174139857292,-0.10948471724987,1.0981794595718 48 | 0.4567768573761,-0.1323037147522,1.0892876386642 49 | 0.43369022011757,-0.15878528356552,1.0848625898361 50 | 0.41369491815567,-0.18682855367661,1.0840229988098 51 | 0.39845454692841,-0.21110381186008,1.0903940200806 52 | 0.38582348823547,-0.23167583346367,1.1031458377838 53 | 0.3750461935997,-0.24713242053986,1.1200432777405 54 | 0.36881673336029,-0.25819209218025,1.1375017166138 55 | 0.36568781733513,-0.26485785841942,1.1564513444901 56 | 0.37185782194138,-0.2690044939518,1.1807118654251 57 | 0.37796437740326,-0.26335248351097,1.201918721199 58 | 0.38775587081909,-0.25119721889496,1.2222570180893 59 | 0.40138012170792,-0.23391284048557,1.2402429580688 60 | 0.41572138667107,-0.21486921608448,1.257496714592 61 | 0.43168851733208,-0.19367448985577,1.2745530605316 62 | 0.44900760054588,-0.17302204668522,1.2915514707565 63 | 0.46780946850777,-0.15567865967751,1.3101243972778 64 | 0.48622307181358,-0.14077790081501,1.329238653183 65 | 0.50343418121338,-0.12818844616413,1.3480852842331 66 | 0.52066373825073,-0.1235304325819,1.3692765235901 67 | 0.53689754009247,-0.12325820326805,1.390322804451 68 | 0.55209898948669,-0.12869265675545,1.4108097553253 69 | 0.56424671411514,-0.14063429832458,1.4305158853531 70 | 0.5729004740715,-0.15547776222229,1.4493339061737 71 | -------------------------------------------------------------------------------- /samples/spiral.csv: -------------------------------------------------------------------------------- 1 | # Create a spiral pattern 2 | # Args: num arms, num points per arm, arms offset, rate of expansion, z step 3 | #spiral, 12, 20, 3, 5, 2 4 | spiral, 6, 20, 6, 5, 2 5 | -------------------------------------------------------------------------------- /samples/spiralcube.csv: -------------------------------------------------------------------------------- 1 | # Create a spiral cube pattern 2 | # Args: point count, rotation in degrees, length to grow line 3 | #spiralcube, 60, 95, 0.6 4 | spiralcube, 60, 89, 0.6 5 | --------------------------------------------------------------------------------