gumyr / build123d

A python CAD programming library
Apache License 2.0
520 stars 88 forks source link

Can't figure out what providing an Axis object to a Locations context does based on documentation #735

Open weerasuriya opened 4 days ago

weerasuriya commented 4 days ago

Hi,

I'm trying to work out what the effect of providing a custom Axis object to the Locations context actually is, in terms of placement:

#%%
from build123d import *
from ocp_vscode import show

#%%
with BuildSketch() as sq:
    Rectangle(10, 10)
    with Locations(Axis((5, 5), (1, 1))):
        Rectangle(1, 1, align=Align.CENTER, mode=Mode.SUBTRACT)

show(sq)

Here, I would have expected the new Axis is the diagonal line y=x. The origin is at (5, 5), so I would expect the smaller cut out square to be placed there. The cutout is centered on (0, 0).

I can't figure out why this behaviour occurs from the docs.

Could anyone advise?

gumyr commented 4 days ago

All sketches must be aligned to Plane.XY but here you've created a Rectangle perpendicular to Plane.XY centered at (5,5,0). The builder code attempts to realign the Rectangle to Plane.XY but in doing so it fails and the Rectangle become centered at the origin. It seems like the builder code should be able to handle this case but it does seems like a strange thing to attempt to do - is there a reason why you are doing this?

Effectively, this is what is happening internally:

face = Axis((5, 5), (1, 1)).location * Rectangle(1, 1).face()
plane = Plane(origin=(0, 0, 0), x_dir=(1, 0, 0), z_dir=face.normal_at())
new_face1 = plane.to_local_coords(face)
new_face2 = new_face1.moved(Location((0, 0, -new_face1.center().Z)))

image

weerasuriya commented 3 days ago

Hello.

Firstly, thanks for the package. It looks great.

I was trying to build a mental model of how the Locations() context works, particularly when the argument is an Axis() (what does it mean to locate on an axis?). I could not reason through what I was seeing. Your explanation helps. It seems perhaps this is an edge case that is unlikely to occur in practical use.

Is it the same phenomenon happening here;

# %%
f3 = Rectangle(0.5, 0.5)
p1 = Axis((1, 1), (1, 1)).to_plane()
f4 = p1.to_local_coords(f3)
show(f3, f4, p1)

f4 should be centered at the origin of p1, but instead is placed at (0,0,0), albeit rotated for some reason.

gumyr commented 3 days ago

A Location has 6 values - 3 positions (X, Y, Z) and 3 orientation angles (rotations about Axis.X, Y & Z). When one creates a location from an Axis the following is done: Location(Plane(origin=self.position, z_dir=self.direction)) where self is the Axis. In this case the resulting Location is oriented along the direction of the Axis which is perpendicular to the plane of the sketch which is causing the trouble.

to_local_coords is kinda like reorienting the plane back to Plane.XY which in this case moves f3 to below Plane.XY - try to image f3 and p1 being locked together and then moving p1 to Plane.XY.

You're the first to report this problem so it appears to be rare that users would want to do this but I'm happy there is an issue to track it so it can be fixed.