SolidCode / SolidPython

A python frontend for solid modelling that compiles to OpenSCAD
1.11k stars 173 forks source link

Null/empty SolidPython object? #70

Closed nerdfever closed 7 years ago

nerdfever commented 7 years ago

Is there a cleaner way to get a null/empty SolidPython object than cube(0), as I've done below?

def label(string, width, halign="left", valign="baseline", size=10, depth=0.5, 
         lineSpacing=1.15, font="MgOpen Modata:style=Bold"):

    """Renders a multi-line string into a single object."""

    lines = string.splitlines()

    result = cube(0)

    for idx, s in enumerate(lines):

        t = text(text=s, halign=halign, valign=valign, font=font)
        t = linear_extrude(height=1)(t)
        t = translate([0, -size * idx * lineSpacing, 0])(t)

        result += t

    result = resize([width, 0, depth], auto=True)(result)
    result = translate([0, (len(lines)-1)*size / 2, 0])(result)

    return result

Note that result starts out empty, then gets unioned with t in each pass thru the loop (result += t).

This seems to work OK, but I'd be happier with a truly empty object instead of a size-0 cube.

etjones commented 7 years ago

As an empty object, I usually use a union(). If you build up objects through concatenation +=, the current parser ends up with a big tree of unions. If you just take the union of a list of separate objects, there should be only one union.

I think what you want is (untested, but it's somewhere in this alley):

def label(string, width, halign="left", valign="baseline", size=10, depth=0.5, 
         lineSpacing=1.15, font="MgOpen Modata:style=Bold"):

    """Renders a multi-line string into a single object."""

    lines = string.splitlines()

    all_ts = []
    for idx, s in enumerate(lines):

        t = text(text=s, halign=halign, valign=valign, font=font)
        t = linear_extrude(height=1)(t)
        t = translate([0, -size * idx * lineSpacing, 0])(t)
        all_ts.append(t)

    result = union()(all_ts)

    result = resize([width, 0, depth], auto=True)(result)
    result = translate([0, (len(lines)-1)*size / 2, 0])(result)

    return result
nerdfever commented 7 years ago

Thanks! I did notice the output took a long time to load into OpenSCAD.

I didn't know union()([ list_contents ]) would union all the elements of a list - that ought to be documented (it's quite handy).

etjones commented 7 years ago

You're right! Somebody ought to look into that one ;-) I think the slow speed is mostly that text() is really intensive; lots and lots of segments there. If you're lucky the single union will speed things up!