Help learning a better way to script this


#1

Second attempt at python. this does what I need it to do but i’m sure there is a better/proper way.

If anyone has some time to check it out and maybe give suggestions on how to do this better, especially with how i did the direction of the flag and just repeating the points with the X coordinates. also i’m sure i could have done something else instead of creating the flag at 0,0 and then moving it.

Thanks in advance, much appreciated.

import rhinoscriptsyntax as rs

def AddFlagNote():

    # some constants
    fontSize = 0.125
    printWidth = 0.60

    # draw leader line
    leaderPoints = rs.GetPoints(True, False, "Select leader points")
    leader_line = rs.AddLeader(leaderPoints)
    leader_end = leaderPoints[-1]

    # test direction for flag orientation
    vector = rs.VectorCreate(leader_end, leaderPoints[-2])

    if vector[0] < 0:

        # points left flag
        pt01 = (0.0, 0.0, 0.0)
        pt02 = (-0.1875, -0.125, 0.0)
        pt03 = (-0.5625, -0.125, 0.0)
        pt04 = (-0.5625, 0.125, 0.0)
        pt05 = (-0.1875, 0.125, 0.0)
        ptText = (-0.375, 0, 0,)

        # draw left facing flag curve
        flag_crv = rs.AddPolyline(pt01 + pt02 + pt03 + pt04 + pt05)
        rs.Command("_CloseCrv SelId %s _Enter" % flag_crv)
        rs.ObjectPrintWidth(flag_crv, printWidth)
        # print "vector neg"
    else:
        # points right flag
        pt01 = (0.0, 0.0, 0.0)
        pt02 = (0.1875, -0.125, 0.0)
        pt03 = (0.5625, -0.125, 0.0)
        pt04 = (0.5625, 0.125, 0.0)
        pt05 = (0.1875, 0.125, 0.0)
        ptText = (0.375, 0, 0,)

        # draw right facing flag curve
        flag_crv = rs.AddPolyline(pt01 + pt02 + pt03 + pt04 + pt05)
        rs.Command("_NoEcho _CloseCrv SelId %s _Enter" % flag_crv)
        rs.ObjectPrintWidth(flag_crv, printWidth)
        # print "vector pos"


    # turn redraw off
    rs.EnableRedraw(False)

    # hatch flag
    hatch_id = rs.AddHatch(flag_crv)
    rs.ObjectPrintColor(hatch_id, (255, 255, 255))

    # get flag text
    flagPrompt = rs.GetString("Enter note number:")
    flagText = rs.AddText(flagPrompt, ptText, fontSize, justification=2 + 131072)


    objs2 = (flag_crv, hatch_id, flagText)
    rs.MoveObject(objs2, leader_end) # move flag group to point
    rs.SelectObjects(objs2)
    rs.Command("_NoEcho _BringToFront _SelNone")

    # group all together
    my_group = rs.AddGroup(group_name=None)
    objs1 = (leader_line, flag_crv, hatch_id, flagText)
    rs.AddObjectsToGroup(objs1, my_group)


    # turn redraw back on
    rs.EnableRedraw(True)

AddFlagNote()

(Thomas Wortmann) #2

Here’s some (untested) ideas to make this clearer and shorter:

  • To be neat, I would make variables for x and y and store the points in a list
  • Instead of the “Close” command, you can get a closed poly-line by using the start point also as the last point in a list
  • The left and right cases seem to be the same, expect for the sign of the x values. So I would have a short block that takes care of both cases (for left we just negate all x values in the point list)

I’m sure that this can be even more perfect, but it’s a start :wink:

def mirrorX(pt):
   pt[0] = pt[0] * -1
   return pt

#Variables
x1 = 0.1875
x2 = 0.375
x3 = 0.5625
y1 = 0.125

#Make list with six zero points (start and end will be the same)
pts = list(itertools.repeat([0.0, 0.0, 0.0], 6))

pts[1] = [x1, -y1, 0.0]
pts[2] = [x3, -y1, 0.0]
pts[3] = [x3, y1, 0.0]
pts[4] = [(x1, y1, 0.0]

ptText = [x2, 0.0, 0.0]

#For left arrow
if vector[0] >= 0.0:
    pts = [mirrorX(pt) for pt in pts]
    ptText = mirrorX(ptText)

# draw flag curve
flag_crv = rs.AddPolyline(pts)
rs.ObjectPrintWidth(flag_crv, printWidth)

#3

awesome! thank you so much for taking the time to reply.

time to dissect and learn! :grinning:


(Steve Baer) #4

I would recommend keeping everything in a function like you initially did. In general this is going to make your script easier to maintain not to mention allowing for early exit from the function in cases where you may want to bail out.


#5

are you suggesting to leave the points lists as is instead of performing mirroring within the script?


(Steve Baer) #6

Sorry for the confusion. I was merely pointing out that it is good practice to place all of your code inside functions.

def AddFlagNote():
   ...
   this is good
   ...

AddFlagNote()