Skip to content
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

Allow user to define a vector for the extrusion direction #81

Closed
gonuke opened this issue Sep 6, 2021 · 12 comments · Fixed by #84
Closed

Allow user to define a vector for the extrusion direction #81

gonuke opened this issue Sep 6, 2021 · 12 comments · Fixed by #84
Assignees
Labels
enhancement New feature or request

Comments

@gonuke
Copy link

gonuke commented Sep 6, 2021

As far as I can tell, the extruded shapes are all derived from Shape and extruded in a direction normal to the workplane and then rotated according to the definition of the rotation_axis and the azimuth_placement_angle.

However, a user frequently knows the unit vector along which they want the extrusion to occur, so it would be convenient if the various extruded shape classes could automatically calculate the rotation_axis and azumuth_placement_angle from that unit vector and the original workplane normal. Perhaps this is how path_workplane should work (?) but I can't find much documentation on that.

Even better would be a way to define this data in a number of ways:

  • staring point (x,y,z) and ending point (x,y,z)
  • unit vector of extrusion direction, reference point (x,y,z) and extents (-l1,l2)
  • unit vector of extrusion direction, starting point (x,y,z) and length [this is a special case of the previous where the reference point is the starting point and the extents are (0,L)]
@shimwell
Copy link
Member

shimwell commented Sep 7, 2021

Hi @gonuke thanks for the suggestion. It makes a lot of sense and would be a nice upgrade.

This is not exactly what you asked for but perhaps of interest
sweep shapes allow a list of coordinates to specified and will sweep a cross section between the coordinates.
https://paramak.readthedocs.io/en/main/paramak.parametric_shapes.html#swept-shapes
If there are only two points in the path_points then it is effectively an extrude.

import paramak

test_shape = paramak.SweepStraightShape(
    points=[(-10, 10), (10, 10), (10, -10), (-10, -10)],
    path_points=[(50, 0), (50, 150)]
)

test_shape.show()

Screenshot from 2021-09-07 20-51-31

I'm going to dig into the CadQuery documentation a bit and see what can be done to enhance the extrude shapes and see if how to go about accepting a unit vector

@gonuke
Copy link
Author

gonuke commented Sep 8, 2021

Will the working plane of the shape be rotated to be normal to this path?

@shimwell
Copy link
Member

shimwell commented Sep 8, 2021

Unfortunately not.

@shimwell
Copy link
Member

shimwell commented Sep 8, 2021

I think I would need to add some new args based on the cadquery vector class https://cadquery.readthedocs.io/en/latest/classreference.html#cadquery.Vector
I've used that before but it looks like the right direction to go in.

@gonuke
Copy link
Author

gonuke commented Sep 10, 2021

That may be one approach, but someone on my team was already doing some rotation math to work around thus by calculating the rotation operations to convert from one of those convenient forms to the rotation system already supported

@shimwell
Copy link
Member

Interesting, @RemDelaporteMathurin will be interested in that, he made a point rotation function and recently raised an issue requested rotation methods

@RemDelaporteMathurin
Copy link
Member

@shimwell @gonuke this is indeed a feature that - i think - is not yet implemented in the Paramak.
Do we agree that this is the expected behaviour? (apologies, my drawing skills are obviously a bit rusty)
With v the unit vector of the extrusion?
image

I think this behaviour could be obtained with sweep shapes but that's maybe using a sledgehammer to beat a fly.

Cadquery natively provides a method to achieve this.

The class ExtrudeMixedShape (and in particular its create_solid method) would need to be extended a bit but that seem feasible to me.

@RemDelaporteMathurin
Copy link
Member

As far as I can tell, the extruded shapes are all derived from Shape and extruded in a direction normal to the workplane and then rotated according to the definition of the rotation_axis and the azimuth_placement_angle.

Not exactly. The parametric shapes are either extruded or rotated. The first step is to give a bunch of points describing a 2D shape (eg the black square I draw above). This 2D shape is then extruded or rotated around a rotation axis (according to rotation_angle).

The azimuth_placemen_angle can be seen as the position of the 2D shape before rotating it.

@RemDelaporteMathurin
Copy link
Member

This seems to do the job.

I shall integrate it asap in a new PR.

image

from paramak import ExtrudeMixedShape, Shape
from paramak.utils import calculate_wedge_cut
from cadquery import Vector, Solid


class ExtrudeMixedShapeBis(ExtrudeMixedShape):
    def __init__(self, extrusion_vector='ortho', **kwargs):
        super().__init__(**kwargs)
        self.extrusion_vector = extrusion_vector

    def create_solid(self):
        """Creates an extruded 3d solid using points connected with straight
        and spline edges.

           Returns:
              A CadQuery solid: A 3D solid volume
        """

        workplane = Shape.create_solid(self)

        if not self.extrude_both:
            extrusion_distance = -self.distance
        else:
            extrusion_distance = -self.distance / 2.0

        wire = workplane.close()
        self.wire = wire

        if type(self.extrusion_vector) is str and self.extrusion_vector == 'ortho':
            solid = wire.extrude(
                distance=extrusion_distance,
                both=self.extrude_both)
        else:
            wireSets = [list(wire.ctx.pendingWires)]
            solid = Solid.extrudeLinear(
                outerWire=wireSets[0][0],
                innerWires=[],
                vecNormal=self.extrusion_vector,
                taper=0
            )

        # filleting rectangular port cutter edges
        # must be done before azimuthal placement
        if hasattr(self, "add_fillet"):
            solid = self.add_fillet(solid)

        solid = self.rotate_solid(solid)
        cutting_wedge = calculate_wedge_cut(self)
        solid = self.perform_boolean_operations(solid, wedge_cut=cutting_wedge)
        self.solid = solid

        return solid


points = [
    (0, 0, "straight"),
    (1, 0, "straight"),
    (1, 1, "straight"),
    (0, 1, "straight"),
]

my_shape = ExtrudeMixedShapeBis(points=points, distance=1, extrusion_vector=Vector((1, 1, 1)))  # 
my_shape.export_stl('out.stl')

@RemDelaporteMathurin RemDelaporteMathurin self-assigned this Sep 13, 2021
@RemDelaporteMathurin RemDelaporteMathurin linked a pull request Sep 13, 2021 that will close this issue
10 tasks
@RemDelaporteMathurin RemDelaporteMathurin added the enhancement New feature or request label Sep 13, 2021
@zxo102
Copy link

zxo102 commented Sep 13, 2021

@gonuke pytransform3d may help. Check pytransform3d's documentation. As mentioned in it's README.md, you can easily extract the relevant code for your purpose.

@RemDelaporteMathurin
Copy link
Member

@gonuke I think I've now understood what you wanted to do: extrude a 2D shape in the workplane normal direction but define the workplane from a normal vector.

Can you please confirm?

If so, I've managed to achieve this with minimal changes to the code.

In red below is the rotated_solid with extrusion direction (1, 1, 1).

image

Code:

import paramak
from cadquery import Plane


points = [
    (0, 0),
    (1, 0),
    (1, 1),
    (0, 1)
]

shape_1 = paramak.ExtrudeStraightShape(points=points, distance=1)

normal_vec = (1, 1, 1)

shape_2 = paramak.ExtrudeStraightShape(
    points=points, distance=1,
    workplane=Plane(origin=(0, 0, 0), xDir=(-1, 1, 0), normal=normal_vec),
    rotation_axis=[(0, 0, 0), normal_vec])

shape_1.export_stl('non_rotated.stl')
shape_2.export_stl('rotated.stl')

@shimwell
Copy link
Member

shimwell commented Sep 21, 2021

solved in PR #84

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
4 participants