<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Fusion performance issue when scaling in Fusion API and Scripts Forum</title>
    <link>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8358476#M15297</link>
    <description>&lt;P&gt;I just tried it but did not notice any problem. I would appreciate if you can share script just in case I did not understand the problem properly.&lt;/P&gt;</description>
    <pubDate>Thu, 25 Oct 2018 10:13:53 GMT</pubDate>
    <dc:creator>goyals</dc:creator>
    <dc:date>2018-10-25T10:13:53Z</dc:date>
    <item>
      <title>Fusion performance issue when scaling</title>
      <link>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8356209#M15296</link>
      <description>&lt;DIV&gt;&lt;SPAN&gt;I'm experiencing a Fusion scaling issue demonstrated with the api where the execution time per api call grows linearly with the number of calls within a single run of a Python script or AddIn.&amp;nbsp; I believe this is a&amp;nbsp;Fusion issue and not an API issue so please don't move to API forum.&amp;nbsp; I put together a simple script which does the following sequence 100 times and measures the execution times for each call. &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;- creates a component copy or occurrence with a single 3D body&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;- creates a sketch (in a different component) which matches a planner face perimeter on the 3D body&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;- creates a joint between the center of the 3D body face and the center of sketch created&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;The following graph show the resulting execution times. This issue has prevented my AddIn MapBoards from behaving well when scaling.&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;IMG src="https://mail.google.com/mail/u/0?ui=2&amp;amp;ik=b04da8960f&amp;amp;attid=0.1&amp;amp;permmsgid=msg-a:r-6403031770771615218&amp;amp;view=fimg&amp;amp;sz=s0-l75-ft&amp;amp;attbid=ANGjdJ-Sh3bpeif7ht0RiRWBfjj4V9vvhSdpVBRgvgUa61ryUXRhqsrGDKC9zt8VP0yBSXa_NojMiA4_fABrwTWX81RhRqzuY3ApN4lxthcEyIQO_05y9W06KUWIsfg&amp;amp;disp=emb&amp;amp;realattid=ii_jnm56p2m0" border="0" alt="image.png" width="542" height="331" /&gt;&lt;/DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Wed, 24 Oct 2018 14:39:19 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8356209#M15296</guid>
      <dc:creator>balunist</dc:creator>
      <dc:date>2018-10-24T14:39:19Z</dc:date>
    </item>
    <item>
      <title>Re: Fusion performance issue when scaling</title>
      <link>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8358476#M15297</link>
      <description>&lt;P&gt;I just tried it but did not notice any problem. I would appreciate if you can share script just in case I did not understand the problem properly.&lt;/P&gt;</description>
      <pubDate>Thu, 25 Oct 2018 10:13:53 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8358476#M15297</guid>
      <dc:creator>goyals</dc:creator>
      <dc:date>2018-10-25T10:13:53Z</dc:date>
    </item>
    <item>
      <title>Re: Fusion performance issue when scaling</title>
      <link>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8359007#M15298</link>
      <description>&lt;PRE&gt;#Description - Demonstrate Fusion scaling issue
#Author-Icarus

import time, traceback
import adsk.core, adsk.fusion

class Stopwatch(object):
    def __init__(self):
        self._elapsed = 0
        self._started = -1

    @property
    def elapsed(self):
        return self._elapsed

    @property
    def started(self):
        return self._started

    def run(self):
        self._elapsed = 0
        self._started = time.perf_counter()

    def interval(self, start=None):
        intvl = 0
        if start is None and self._started &amp;gt; 0:
            intvl = time.perf_counter() - self._started
            self._elapsed += intvl
            self._started = time.perf_counter()
        else:
            intvl = time.perf_counter() - start
        return intvl


timer = Stopwatch()


class dim:

    def __init__(self, units, value):
        self.units = units
        self.value = value

    def add(self, x):
        self.value += x

    def __str__(self):
        return "{}{}".format(self.value, self.units)

    def dispdim(self):  # used for Text out and debug
        return "{}{}".format(self.value, self.units)


class Rect:
    def __init__(self, insert=(0, 0), size=(0, 0)): 
        app = adsk.core.Application.get()
        design = adsk.fusion.Design.cast(app.activeProduct)
        self.unitsManager = design.unitsManager
        x = self.convertToInternal(insert[0])
        y = self.convertToInternal(insert[1])
        self.defaultLength = size[0]
        self.defaultWidth = size[1]
        self.length = self.convertToInternal(size[0])
        self.width = self.convertToInternal(size[1])
        self.startPoint = adsk.core.Point3D.create(x, -y, 0)
        self.endPoint = adsk.core.Point3D.create(x + self.length, -(y + self.width), 0)

    def convertToInternal(self, valueIn):
        return self.unitsManager.convert(valueIn, self.unitsManager.defaultLengthUnits, self.unitsManager.internalUnits)


class Board:

    def __init__(self, source, desx, desy, length, width):
        self.targetComp = source.targetComp
        self.desy = desy  # will update to the next board position
        self.kerf = 0.125
        self.edge_trim = 0.25
        self.board_top_x = desx.value
        self.board_top_y = desy.value
        self.length = length
        self.width = width

        sketch = self.targetComp.sketches.add(self.targetComp.xYConstructionPlane)
        sketchLines = sketch.sketchCurves.sketchLines

        bd_rect = Rect(insert=(self.board_top_x, self.board_top_y), size=(length, width))
        sketchLines.addTwoPointRectangle(bd_rect.startPoint, bd_rect.endPoint)
        self.desy.add(self.width + bd_rect.convertToInternal(.80))

        # adjust for perimeter spacing
        self.board_top_x += self.edge_trim
        self.board_top_y += self.edge_trim
        self.length -= (self.edge_trim * 2)
        self.width -= (self.edge_trim * 2)

    def fill(self, source, count):
        pass


class DiagonalBoard(Board):

    def __init__(self, source, desx, desy, length=96, width=48):
        super().__init__(source, desx, desy, length, width)
        self.queue = []

    def fill_space(self, source, top_x, top_y, width, length):

        if source.comp_width &amp;gt; width or source.comp_length &amp;gt; length:
            return True

        timer.run()

        comp, bodies = source.new_comp()

        face_areas = []
        for face in bodies[0].faces:
            face_areas.append(face.area)
        idx = face_areas.index(max(face_areas))
        source_face = bodies[0].faces.item(idx)
        new_occurrence = timer.interval()

        # create target sketch profile
        sketch = self.targetComp.sketches.add(self.targetComp.xYConstructionPlane)
        sketchLines = sketch.sketchCurves.sketchLines
        target_rect = Rect(insert=(top_x, top_y), size=(source.comp_length, source.comp_width))
        sketchLines.addTwoPointRectangle(target_rect.startPoint, target_rect.endPoint)
        idx = len(sketch.profiles) - 1
        target_prof = sketch.profiles.item(idx)
        new_sketch = timer.interval()

        # create joint between body's largest face to profile
        geo0 = adsk.fusion.JointGeometry.createByPlanarFace(source_face, None,
                                                            adsk.fusion.JointKeyPointTypes.CenterKeyPoint)
        geo1 = adsk.fusion.JointGeometry.createByProfile(target_prof, None,
                                                         adsk.fusion.JointKeyPointTypes.CenterKeyPoint)

        joints = comp.joints
        joint_input = joints.createInput(geo0, geo1)
        joint_input.setAsPlanarJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection)
        joint_input.isFlipped = True
        joint = joints.add(joint_input)

        new_joint = timer.interval()

        total = new_occurrence + new_sketch + new_joint + timer.elapsed
        print('{}, {}, {}, {}'.format(new_occurrence, new_sketch, new_joint, timer.elapsed, total))

        length_left = length - (source.comp_length + self.kerf)
        width_left = width - (source.comp_width + self.kerf)

        if width_left &amp;gt; 0:
            self.queue.insert(0, (top_x, top_y + source.comp_width + self.kerf, width_left,
                                  source.comp_length))

        if length_left &amp;gt; 0:
            self.queue.insert(0, (top_x + source.comp_length + self.kerf, top_y, width,
                                  length_left))
        return True

    def fill(self, source):

        self.queue.insert(0, (self.board_top_x, self.board_top_y, self.width, self.length))

        while source.count &amp;gt; 0 and len(self.queue) &amp;gt; 0:

            source.count -= 1
            item = self.queue.pop()
            self.fill_space(source, item[0], item[1], item[2], item[3])


class FillBoards:
    def __init__(self, source):
        self.source = source
        self.desx = dim('in', 0)
        self.desy = dim('in', 0)

    def run(self):

        timer.run()
        start_time = timer.started

        print('\nOccurrence, Sketch, Joint, Total')
        while self.source.count &amp;gt; 0:
            try:
                bd = DiagonalBoard(self.source, self.desx, self.desy)  # desy updated past previous board
                bd.fill(self.source)  # returns when board full or component count equals zero

            except:
                raise  # send it along

        print('bodies placed: {}'.format(timer.interval(start_time)))


class SourceBase:
    def __init__(self, map_comp, name):
        self.sourceOcc = map_comp.sourceOcc
        self.sourceComp = map_comp.sourceComp
        self.xYPlane = self.sourceComp.xYConstructionPlane
        self.baseOcc = self.sourceComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        self.baseComp = self.baseOcc.component 
        self.baseComp.name = name
        self.source_sketch = self.sourceComp.sketches.add(self.sourceComp.xYConstructionPlane)
        self.targetOcc = map_comp.targetOcc
        self.targetComp = map_comp.targetComp

    def _create_body(self):
        self.thick = .75 * 2.54
        self.targetProf1 = self.source_sketch.profiles.item(0)
        
        profiles = adsk.core.ObjectCollection.create()
        profiles.add(self.targetProf1)
       
        extrudeFeats = self.comp.features.extrudeFeatures
        extrudeFeature = extrudeFeats.addSimple(profiles, 
                                                adsk.core.ValueInput.createByReal(self.thick),
                                                adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        self.body = extrudeFeature.bodies.item(0)                                        
        self.bodies = adsk.core.ObjectCollection.create()
        self.bodies.add(self.body )

    def new_comp(self):
        compOcc = self.targetComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        comp = compOcc.component  
        # comp.name = name
        self.body.copyToComponent(compOcc)
        bodyOcc = compOcc.bRepBodies.item(0)
        # bodyOcc.name = name
        bodies = adsk.core.ObjectCollection.create()
        bodies.add(bodyOcc)
        return comp, bodies


class PlankSource(SourceBase):
    def __init__(self, map_comp, count):
        super().__init__(map_comp, 'Plank')
        self.count = count
        self.compOcc = self.baseComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        self.comp = self.compOcc.component  
        self.comp.name = 'Plank'
        sketchLines = self.source_sketch.sketchCurves.sketchLines
        
        compRect = Rect(insert=(0, -4), size=(18, 4))
        self.comp_length = compRect.defaultLength
        self.comp_width = compRect.defaultWidth
        self.thick = .75 * 2.54  # inches
        self.widthInternal = compRect.width        
        
        sketchLines.addTwoPointRectangle(compRect.startPoint, compRect.endPoint)

        self._create_body()

  
class CreateMapSource:
    def __init__(self):    
        app = adsk.core.Application.get()
        act_doc = app.activeDocument.dataFile
        if act_doc is not None:
            app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
       
        design = adsk.fusion.Design.cast(app.activeProduct)
        self.rootComp = design.rootComponent
        occs = self.rootComp.occurrences
        for occ in occs:
            if occ.component.name.startswith('map'):
                occ.deleteMe()
                break
        for occ in occs:
            if occ.component.name.startswith('map'):
                occ.deleteMe()
                break

        self.rootComp = design.rootComponent
        self.sourceOcc = self.rootComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        self.sourceComp = self.sourceOcc.component  
        self.sourceComp.name = 'mapSource'
        self.targetOcc = self.rootComp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        self.targetComp = self.targetOcc.component
        self.targetComp.name = 'mapTarget'


def run(context):
    try:

        map_comp = CreateMapSource()
        planks = PlankSource(map_comp, 100)  # number of passes

        mapper = FillBoards(planks)

        mapper.run()

    except Exception:
        traceback.print_exc()
        
    finally:
        pass

&lt;/PRE&gt;</description>
      <pubDate>Thu, 25 Oct 2018 13:08:10 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/fusion-api-and-scripts-forum/fusion-performance-issue-when-scaling/m-p/8359007#M15298</guid>
      <dc:creator>balunist</dc:creator>
      <dc:date>2018-10-25T13:08:10Z</dc:date>
    </item>
  </channel>
</rss>

