SolidCode / SolidPython

A python frontend for solid modelling that compiles to OpenSCAD
1.1k stars 171 forks source link

Please add some multi-transform examples to the documentation #186

Open charlieb opened 2 years ago

charlieb commented 2 years ago

There are no examples in the documentation of situations where you want to chain several transformations together e.g.

s.translate([-4, 0, 8])(
    s.rotate([0, 20 + 9, 10])(
        s.scale([1, 2, 0.5])(
            s.sphere(r=10))))

I think it would be instructive to have an example showing the correct way to do this.

etjones commented 2 years ago

From the look of #185, it seems like you had some different expectations about how composed transformations would work. I think that SolidPython & OpenSCAD process those nested transformations identically. Can you think of a minimal example that would have made this more clear to you? I don’t think I quite understand the ambiguity you’d been seeing.

On Sep 19, 2021, at 9:29 AM, Charlie Burrows @.***> wrote:

There are no examples in the documentation of situations where you want to chain several transformations together e.g. s.translate([-4, 0, 8])( s.rotate([0, 20 + 9, 10])( s.scale([1, 2, 0.5])( s.sphere(r=10))))

I think it would be instructive to have an example showing the correct way to do this.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/SolidCode/SolidPython/issues/186, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEWGLNQJAAI7K22QEQMATLUCXXWDANCNFSM5EKMVJUQ. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

charlieb commented 2 years ago

I don't disagree with you about the semantics. I've personally never used a construction where you have a simple transformation with a {} block after it in OpenSCAD so I guess it's no surprise that I don't expect it in python either. I've been missing a trick.

What I expected from this code:

t = s.translate([-4, 0, 8])(s.rotate([0, 20 + 9, 10]))
obj = t(s.sphere(r=10))

is that t would be a callable that would rotate then translate its argument. The (incorrectly) unexpected part is that what actually happens is that t is a translation at the root of a tree where one branch has a rotation on it, and calling it again adds another branch to the translation rather than adding to the end of the chain of transforms that I thought I created.

All that aside, I wouldn't have had to try come to any conclusions if there were examples the covered chained transformations. In fact I couldn't find any examples to follow that had more than a single transform applied to an object. I think if I had been able to find a simple example of chained transforms all this unpleasantness would have been avoided.

Neon22 commented 2 years ago

so in Openscad this would be :

module t(radius=10) {
   translate([-4,0,8])
   rotate([0,29,10])
   sphere(r=radius);
}
t();
// or t(10);

(Because they follow each other we don't need any {} for grouping)

jeff-dh commented 2 years ago

One could add an translation of the basic OpenSCAD Tutorial (https://en.wikibooks.org/wiki/OpenSCAD_Tutorial/Chapter_1#Completing_your_first_model)

The exp solid branch contains an example like it but with a different focus (and syntax): https://github.com/jeff-dh/SolidPython/blob/exp_solid/solid/examples/06-functions.py

The intention was to give an example how to assemble more complex models and I think that's what you're asking for, right?

charlieb commented 2 years ago

It doesn't have to be that much, like that's a long tutorial, but yes I'm essentially asking for a snippet that demonstrates a few transforms in a chain.

jeff-dh commented 2 years ago

I thought about something like this:

wheel_radius = 50
wheel_thickness = 15
wheel_offset = 100

axle_radius = 5
axle_offset = 150

wheel = cylinder(wheel_radius, wheel_thickness, center=True).rotate(0, 90, 0)

axle = wheel.forward(axle_offset).left(wheel_offset) + \
           wheel.forward(axle_offset).right(wheel_offset) + \
           cylinder(axle_radius, wheel_offset*2, center=True).rotate(0, 90, 0).forward(axle_offset)

car = axle + axle.back(axle_offset*2) + \
         cube(wheel_offset*1.7, axle_offset*2.5, 100, center=True).up(wheel_radius) + \
         cube(wheel_offset*1.7, 150, 150, center=True).up(100)

car.save_as_scad()

This is "expSolid-Style" but should be easily translatable to Solid::master compatible code.

jeff-dh commented 2 years ago

@charlieb Btw: As you correctly analyzed in #185 SolidPython builds (something like ;) a tree, but -- as this example shows -- it's actually a graph ;)

charlieb commented 2 years ago

So the code above, the dotted style won't build for me:

import solid as s                                                       
s.sphere(r=10).rotate([0, 90, 0])

gives

Traceback (most recent call last):
  File "/home/charlieb/src/textures/test.py", line 3, in <module>
    s.sphere(r=10).rotate([0, 90, 0])
AttributeError: 'sphere' object has no attribute 'rotate'

That's a different issue (also no doubt my problem) but yes that instance of ).rotate(0, 90, 0).forward(axle_offset) would be what I'm looking for, only maybe with the alternate syntaxes listed.

jeff-dh commented 2 years ago
# ======================================================
# = add relative path to the solid package to sys.path =
# ======================================================
import sys
from pathlib import Path
solidPath = Path(__file__).absolute().parent.parent.parent.as_posix()
sys.path.insert(0, solidPath)
#======================================================

from solid import *
from solid.utils import *

wheel_radius = 50
wheel_thickness = 15
wheel_offset = 100

axle_radius = 5
axle_offset = 150

wheel = rotate([0, 90, 0])(cylinder(wheel_radius, wheel_thickness, center=True))

axle = left(wheel_offset)(forward(axle_offset)(wheel)) + \
           right(wheel_offset)(forward(axle_offset)(wheel)) + \
           forward(axle_offset)(rotate([0, 90, 0])(cylinder(axle_radius, wheel_offset*2, center=True)))

car = axle + back(axle_offset*2)(axle) + \
         up(wheel_radius/2)(cube([wheel_offset*1.7, axle_offset*2.5, 100], center=True))+ \
         up(100)(cube([wheel_offset*1.7, 150, 150], center=True))

scad_render_to_file(car, "car.scad")

This is master compatible....