Description
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 OpenSCADObject
s 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