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

Skip to content

Cannot pass OpenSCADObject as parameter #157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ebak opened this issue Nov 11, 2020 · 3 comments
Closed

Cannot pass OpenSCADObject as parameter #157

ebak opened this issue Nov 11, 2020 · 3 comments

Comments

@ebak
Copy link

ebak commented Nov 11, 2020

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

@etjones
Copy link
Contributor

etjones commented Nov 12, 2020

Hi Endre - This issue has come up before, but I think this is a possible way forward that would allow us to use imported OpenSCAD code to make calculations as well as create geometry, which is how I wrote this in the first place.

Thanks for your code here! I think this has promise for dealing with polygon(), and I think we may be able to apply it in a few other parts of the code so that all the functions that could take non-geometry arguments could reasonably accept imported OpenSCAD calculations (instances of IncludedOpenSCADObject). More here soon...

@etjones
Copy link
Contributor

etjones commented Nov 16, 2020

Give the version released on PyPI as SolidPython 1.0.3 a try; it should have resolved this issue. In addition, any SolidPython object should be able to take imported OpenSCAD code as an argument to a function, so this should be a general solution to the problem.

There are, I think some complexities to this approach. If you did a set of nested calculations with imported OpenSCAD code, I'm not certain this would represent them correctly. BUT, for most purposes, which is "Somebody did some calculations I need in this OpenSCAD module-- can I just use them in SolidPython?", this should do the trick.

@ebak
Copy link
Author

ebak commented Nov 23, 2020

Hi,

I have verified this with the polygon stuffs. Works great. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants