Reposition the text position of a sketch dimension using the API

Reposition the text position of a sketch dimension using the API

bloudraak
Enthusiast Enthusiast
461 Views
1 Reply
Message 1 of 2

Reposition the text position of a sketch dimension using the API

bloudraak
Enthusiast
Enthusiast

My application is driven by user parameters, and I'm using constraints to determine the actual dimensions rather than calculating it in code. This allows a user to change user parameters, and see the effect of it on the design almost immediately.

 

There's a lot of constraints, specially dimensions. As a result, I've been trying to generate a sketch that can be understood by a user.  When I do this manually, I usually center the text in the line. 

 

The final soltuion I came up with, did not work as it crashes Fusion 360, and it's unclear why.

 

At first, I wrote a function to add a dimension between two sketch points, and center the text on the line.

def add_distance_dimension(sketch, point1, point2, orientation, distance=0.5, parameter=None):
    # Normalize the values
    x1 = min(point1.geometry.x, point2.geometry.x)
    y1 = min(point1.geometry.y, point2.geometry.y)
    x2 = max(point1.geometry.x, point2.geometry.x)
    y2 = max(point1.geometry.y, point2.geometry.y)

    # Get the sketch boundaries
    max_x = sketch.boundingBox.maxPoint.x
    min_x = sketch.boundingBox.minPoint.x
    max_y = sketch.boundingBox.maxPoint.y
    min_y = sketch.boundingBox.minPoint.y

    width = max_x - min_x
    depth = max_y - min_y
    cx = width / 2
    cy = depth / 2

    if orientation == vertical_dimension_orientation:
        y = (y2 - y1) / 2
        if x1 < cx:
            x = min_x - distance
        else:
            x = max_x + distance
    else:
        x = (x2 - x1) / 2
        if y1 < cy:
            y = min_y - distance
        else:
            y = max_y + distance

    app.log(f'text position = ({x}, {y})')

    text_position = adsk.core.Point3D.create(x, y, 0)
    dim = sketch.sketchDimensions.addDistanceDimension(point1, point2, orientation, text_position)
    if parameter:
        dim.parameter.expression = parameter.name

 

The sketch looks something like this afterwards, when it's applied to the rectangle. 

wernersLNPQD_0-1642892147490.png

The code has a defect. The parameter evaluates to be 0.5. Any dimenion not set against the bottom and left sides, and misaligned.

 

wernersLNPQD_2-1642892703208.png

It's evident from the code that this happens because of how the middle was calculated, and it was done BEFORE the point was constrained. I probably have to do it AFTER applying the constraint. So I updated the code to look as follows, and add some logging:

 

def add_distance_dimension(sketch, point1, point2, orientation, distance=0.5, parameter=None):
    # Normalize the values
    x1 = min(point1.geometry.x, point2.geometry.x)
    y1 = min(point1.geometry.y, point2.geometry.y)
    x2 = max(point1.geometry.x, point2.geometry.x)
    y2 = max(point1.geometry.y, point2.geometry.y)
    app.log(f'Before: ({x1}, {y1}) <-> ({x2}, {y2})')

    text_position = adsk.core.Point3D.create(1, 1, 0)
    dim = sketch.sketchDimensions.addDistanceDimension(point1, point2, orientation, text_position)
    if parameter:
        dim.parameter.expression = parameter.name

    x1 = min(point1.geometry.x, point2.geometry.x)
    y1 = min(point1.geometry.y, point2.geometry.y)
    x2 = max(point1.geometry.x, point2.geometry.x)
    y2 = max(point1.geometry.y, point2.geometry.y)
    app.log(f'After: ({x1}, {y1}) <-> ({x2}, {y2})')

    # Get the sketch boundaries
    max_x = sketch.boundingBox.maxPoint.x
    min_x = sketch.boundingBox.minPoint.x
    max_y = sketch.boundingBox.maxPoint.y
    min_y = sketch.boundingBox.minPoint.y

    width = max_x - min_x
    depth = max_y - min_y
    cx = width / 2
    cy = depth / 2

    if orientation == vertical_dimension_orientation:
        y = (y2 - y1) / 2
        if x1 < cx:
            x = min_x - distance
        else:
            x = max_x + distance
    else:
        x = (x2 - x1) / 2
        if y1 < cy:
            y = min_y - distance
        else:
            y = max_y + distance

    text_position = adsk.core.Point3D.create(x, y, 0)
    app.log(f'text position = ({x}, {y})')
    app.log(f'isValid = {dim.isValid}')
    dim.textPosition = text_position

The last line causes Fusion 360 to crash, and generate an error report.

dim.textPosition = text_position

 When I comment out the line, nothing seems out of the ordinary for the logs:

 0 = (0.0,0.0)x(6.267,0.0) 
 1 = (6.267,0.0)x(6.267,8.948) 
 2 = (6.267,8.948)x(0.0,8.948) 
 3 = (0.0,8.948)x(0.0,0.0) 
 Before: (0.0, 0.0) <-> (6.267, 0.0)
 After: (0.0, 0.0) <-> (6.267, 0.0)
 text position = (3.1335, -1.001)
 isValid = True
 Before: (0.0, 0.0) <-> (0.0, 8.948)
 After: (0.0, 0.0) <-> (0.0, 8.948)
 text position = (-1.001, 4.474)
 isValid = True
 Before: (0.0, 0.0) <-> (0.5, 0.5)
 After: (0.0, 0.0) <-> (0.5, 0.5)
 text position = (0.25, -0.501)
 isValid = True
 Before: (0.0, 0.0) <-> (0.5, 0.5)
 After: (0.0, 0.0) <-> (0.5, 0.5)
 text position = (-0.501, 0.25)
 isValid = True
 Before: (0.0, 6.448) <-> (0.5, 8.948)
 After: (0.0, 8.448) <-> (0.5, 8.948)
 text position = (-0.501, 0.25)
 isValid = True
 Before: (0.0, 8.448) <-> (0.5, 8.948)
 After: (0.0, 8.448) <-> (0.5, 8.948)
 text position = (0.25, 9.449)
 isValid = True
 Before: (3.7670000000000003, 0.0) <-> (6.267, 0.5)
 After: (3.7670000000000003, 0.0) <-> (6.267, 0.5)
 text position = (6.768000198364258, 0.25)
 isValid = True
 Before: (3.7670000000000003, 0.0) <-> (6.267, 0.5)
 After: (5.767, 0.0) <-> (6.267, 0.5)
 text position = (0.25, -0.501)
 isValid = True
 Before: (3.7670000000000003, 6.448) <-> (6.267, 8.948)
 After: (3.7670000000000003, 8.448) <-> (6.267, 8.948)
 text position = (6.768000198364258, 0.25)
 isValid = True
 Before: (3.7670000000000003, 8.448) <-> (6.267, 8.948)
 After: (5.767, 8.448) <-> (6.267, 8.948)
 text position = (0.25, 9.449)
 isValid = True

And the documentation doesn't say much either.

 

The code that uses this function looks something like this

    document = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
design = document.products[0]
    units_mgr = design.unitsManager
    units_mgr.distanceDisplayUnits = adsk.fusion.DistanceUnits.MillimeterDistanceUnits
    root = design.rootComponent
    component = root.occurrences.addNewComponent(adsk.core.Matrix3D.create()).component
    margin_p = design.userParameters.add('Margin',
                                         create_real_value(0.5),
                                         'mm',
                                         'A margin of some sorts')
    width = 6.534
    depth = 11.896
    sketch = component.sketches.add(component.xYConstructionPlane)
    sketch.name = "Sketch1"
    lines = sketch.sketchCurves.sketchLines
    p1 = adsk.core.Point3D.create(0, 0, 0)
    p2 = adsk.core.Point3D.create(width + 2, depth + 2, 0)

    rectangle = lines.addTwoPointRectangle(p1, p2)
    bottom = rectangle.item(0)
    top = rectangle.item(2)
    right = rectangle.item(1)
    left = rectangle.item(3)

    for n in range(0, 4):
        g = rectangle.item(n).startSketchPoint.geometry
        h = rectangle.item(n).endSketchPoint.geometry
        app.log(f'{n} = ({g.x},{g.y})x({h.x},{h.y}) ')

    margin = margin_p.value

    points = adsk.core.ObjectCollection.create()
    hlb = sketch.sketchPoints.add(adsk.core.Point3D.create(margin, margin, 0))
    htl = sketch.sketchPoints.add(adsk.core.Point3D.create(margin, depth - margin, 0))
    hrb = sketch.sketchPoints.add(adsk.core.Point3D.create(width - margin, margin, 0))
    hrt = sketch.sketchPoints.add(adsk.core.Point3D.create(width - margin, depth - margin, 0))
    points.add(hlb)
    points.add(htl)
    points.add(hrb)
    points.add(hrt)

    # bottom = 0.0, 0.0
    # right = 8.534, 0.0
    # top = 8.534, 13.896
    # left = 0.0, 13.896

    # Rectangle
    constraints = sketch.geometricConstraints
    constraints.addHorizontal(top)
    constraints.addHorizontal(bottom)
    constraints.addVertical(right)
    constraints.addVertical(left)

    # Make sure rectangle is anchored at the origin.
    constraints.addCoincident(bottom.startSketchPoint, sketch.originPoint)
    add_distance_dimension(sketch, bottom.startSketchPoint, bottom.endSketchPoint, horizontal_dimension_orientation, 1)
    add_distance_dimension(sketch, left.startSketchPoint, left.endSketchPoint, vertical_dimension_orientation, 1)

    add_distance_dimension(sketch, bottom.startSketchPoint, hlb, horizontal_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, left.endSketchPoint, hlb, vertical_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, left.startSketchPoint, htl, vertical_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, top.endSketchPoint, htl, horizontal_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, right.startSketchPoint, hrb, vertical_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, bottom.endSketchPoint, hrb, horizontal_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, right.endSketchPoint, hrt, vertical_dimension_orientation, 0.5, margin_p)
    add_distance_dimension(sketch, top.startSketchPoint, hrt, horizontal_dimension_orientation, 0.5, margin_p)

 

Software Engineer
https://wernerstrydom.com
0 Likes
462 Views
1 Reply
Reply (1)
Message 2 of 2

kandennti
Mentor
Mentor

Hi @bloudraak .

 

Modifying the X and Y values did not cause a crash.

・・・
    # text_position = adsk.core.Point3D.create(x, y, 0)
    app.log(f'text position = ({x}, {y})')
    app.log(f'isValid = {dim.isValid}')
    # dim.textPosition = text_position
    dim.textPosition.x = x
    dim.textPosition.y = y
0 Likes