gumyr/build123d

Extrude faces from SVG sometimes changes direction when applying taper

Opened this issue · 2 comments

import build123d as bd

svg = bd.import_svg("bd_test.svg")
# taper = 0
taper = 10

with bd.BuildPart() as prt:
    with bd.BuildSketch():
        for k in svg:
            with bd.BuildLine():
                bd.add(k)
            bd.make_face()
    bd.extrude(amount=10, taper=taper, dir=bd.Axis.Z.direction)

show(prt)

Depending on what shapes are in the imported SVG, some objects change direction when applying a taper.

This is without taper. Things extrude as expected.
20240218_005027

When applying a taper primitives like rect and cylinder change direction of the extrusion while path behaves like they should.
20240218_005046
bd_test

Thanks for isolating the problem. After removing all of the Python code that I can, here is what happens:

from build123d import *
from ocp_vscode import show
from OCP.LocOpe import LocOpe_DPrism
from math import radians, cos

svg = import_svg("issue-553.svg")
face_to_extrude = -Face(svg[2])
taper = 10

prism_builder = LocOpe_DPrism(
    face_to_extrude.wrapped,
    10 / cos(radians(taper)),
    radians(taper),
)
new_solid = Solid(prism_builder.Shape())

show(face_to_extrude, new_solid)

image
the extrude is in the wrong direction and this direction is independent of the face normal (same result with face_to_extrude = Face(svg[2]).

Need to figure out why LocOpe_DPrism is flipping the direction or avoid using this class at all.

There are a couple solutions to this. One is this:

svg = import_svg("issue-553.svg")
profile = Face(svg[2])
taper = 10

taper_law = Law_Linear()
taper_law.Set(0.0, 1.0, 1.0, 1 - sin(radians(taper)))
outer = profile.outer_wire().wrapped

direction = Vector(0, 0, 10)
spine_p1 = profile.center()
spine_p2 = spine_p1 + Vector(direction)
pipe_shell_spine = Wire(Edge.make_line(spine_p1, spine_p2)).wrapped

extrude_builder = BRepOffsetAPI_MakePipeShell(pipe_shell_spine)
extrude_builder.Add(outer)
extrude_builder.SetLaw(outer, taper_law)
extrude_builder.Build()
extrude_builder.MakeSolid()
taper_solid = extrude_builder.Shape()

show(pipe_shell_spine, taper_solid)

where LocOpe_DPrism is replaced with BRepOffsetAPI_MakePipeShell with a "law" that implements a linear taper.

Alternatively, if I do this:

        if (
            False
            and direction.normalized() == profile.normal_at()
            and Plane(profile).z_dir.Z > 0
            and taper > 0
            and not profile.inner_wires()
        ):

i.e. just disable the use of LocOpe_DPrism in extrude_taper the objects will be created by lofting.

There is an open PR on an improvement to lofting that would allow for holes (but the PR isn't complete), so I'll have to think about which way to go here.