Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Cannot pass OpenSCADObject as parameter #157

Closed
@ebak

Description

@ebak

Hi,

Thanks for creating SolidPython! It is a very useful tool for OpenSCAD.
I have recently started to use its Importing OpenSCAD code feature (https://solidpython.readthedocs.io/en/latest/#importing-openscad-code), and luckily I started with a case which doesn't seem to be supported.

I had problem with the Round-Anything module's polyRound() function: https://kurthutten.com/blog/round-anything-api/

An example OpenSCAD code looks like:

radiiPoints=[[-4,0,1],[5,3,1.5],[0,7,0.1],[8,7,10],[20,20,0.8],[10,0,10]];
polygon(polyRound(radiiPoints,30));

Calling it from SolidPython would look like:

import solid as sd
rounder = sd.import_scad('polyround.scad')

rpoints = [
    (-10, -10, 3), (-10, 10, 3), (10, 10, 3), (10, -10, 3)]

pr = rounder.polyRound(radiipoints=rpoints, fn=32)  # It is an OpenSCADObject
poly = sd.polygon(points=pr)    # OpenSCADObject is passed as parameter

Unfortunately it doesn't work since the constructor of solid.polygon, which cannot take on OpenSCADObject parameters:

    def __init__(self, points: Points, paths: Indexes = None) -> None:
        if not paths:
            paths = [list(range(len(points)))]
        super().__init__('polygon',
                         {'points': _to_point2s(points), 'paths': paths})

It would be very nice to support OpenSCADObjects as paramters.

I have created a very ugly draft patch for myself to make it work:

import solid as sd
import solid.solidpython
from typing import Union, Iterable
from solid.objects import _to_point2s
from solid import OpenSCADObject, Points, Indexes

rounder = sd.import_scad('../SCAD.libs/Round-Anything-master/polyround.scad')


def patched_py2openscad(o: Union[bool, float, str, Iterable]) -> str:
    if isinstance(o, OpenSCADObject):
        return o._render()[:-1]     # PATCH
    if type(o) == bool:
        return str(o).lower()
    if type(o) == float:
        return f"{o:.10f}"  # type: ignore
    if type(o) == str:
        return f'\"{o}\"'  # type: ignore
    if type(o).__name__ == "ndarray":
        import numpy  # type: ignore
        return numpy.array2string(o, separator=",", threshold=1000000000)
    if hasattr(o, "__iter__"):
        s = "["
        first = True
        for i in o:  # type: ignore
            if not first:
                s += ", "
            first = False
            s += patched_py2openscad(i)
        s += "]"
        return s
    return str(o)


class patched_polygon(OpenSCADObject):

    def __init__(self, points: Points, paths: Indexes = None) -> None:
        if isinstance(points, OpenSCADObject):
            super().__init__(
                'polygon',
                {'points': points})
        else:
            if not paths:
                paths = [list(range(len(points)))]
            super().__init__('polygon',
                             {'points': _to_point2s(points), 'paths': paths})


solid.solidpython.py2openscad = patched_py2openscad     # PATCH
sd.polygon = patched_polygon                            # PATCH


rpoints = [
    (-10, -10, 3),
    (-10, 10, 3),
    (10, 10, 3),
    (10, -10, 3)]

pr = rounder.polyRound(radiipoints=rpoints, fn=32)  # It is an OpenSCADObject
poly = sd.polygon(points=pr)    # OpenSCADObject is passed as parameter


def save(sdobj, fname):
    scad = sd.scad_render(sdobj)
    with open(fname, "w") as f:
        f.write(pr.include_string + '\n')   # This is a very ugly workaround!
        f.write(scad)


save(poly, 'example.scad')

Would it be possible to implement a nice solution for this use-case?

Best Regards,
Endre

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions