discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

A simple approach to creating fillets

AM
Adrian Mariano
Fri, Feb 17, 2023 12:44 AM

Really Daniel's original approach is limited and awkward because it
requires having parameterized modules that give the object at different
offsets.  This is not a normal situation, or perhaps even easy to
accomplish, for most nontrivial objects.  If we had a 3d offset(), or were
willing to wait for minkowski() we could do this without those kinds of
assumptions, though it would still require convexity.  (And if you're
using minkowski then maybe just use that for rounding.)  I personally
think my modified approach using scale is more interesting because it
doesn't require having these weird parameterized modules.  And if you say
that it's easy enough to do it for cube and cylinder, well, then you can
make a module with explicit "cube" and "cylinder" options.  Sphere too.

The true right answer is to have access to the geometry and implement an
approach based on the points from the geometry, like I have done in BOSL2
and like Sanjeev has also done.  Right now, though, there is no way to
access the points of geometry, so you need to be able to make your object
some other way, which is also limiting.  Another observation is that if we
had the bounding box and centroid of the objects that would be enough
information to make this method work, at least in many cases.

On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown openscad@jordan.maileater.net
wrote:

Hmm.  One issue is that we're using different meanings for "parameters".
I don't think of an object's translation and rotation, or even scale, as
parameters.  They are transformations externally applied to the object.  I
generally find it offensive to specify a position or rotation as part of
the definition of an object - just as in the real world, an object comes
from the factory, and then I position it where I want it.

And mostly that mental model works well, but not for this algorithm.

For this algorithm, the transformation, rotation, and scale have to be
done in the middle of the algorithm, neither applied to the objects before
the algorithm nor applied to the result afterward.

The reason for that is that the algorithm depends on scaling the objects,
for which they must be at the origin, and then intersecting the objects,
which must be with them at their final positions.

I agree that it's ugly, though perhaps for different reasons than you
think it is.

It makes my head hurt.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Really Daniel's original approach is limited and awkward because it requires having parameterized modules that give the object at different offsets. This is not a normal situation, or perhaps even easy to accomplish, for most nontrivial objects. If we had a 3d offset(), or were willing to wait for minkowski() we could do this without those kinds of assumptions, though it would still require convexity. (And if you're using minkowski then maybe just use that for rounding.) I personally think my modified approach using scale is more interesting because it doesn't require having these weird parameterized modules. And if you say that it's easy enough to do it for cube and cylinder, well, then you can make a module with explicit "cube" and "cylinder" options. Sphere too. The true right answer is to have access to the geometry and implement an approach based on the points from the geometry, like I have done in BOSL2 and like Sanjeev has also done. Right now, though, there is no way to access the points of geometry, so you need to be able to make your object some other way, which is also limiting. Another observation is that if we had the bounding box and centroid of the objects that would be enough information to make this method work, at least in many cases. On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown <openscad@jordan.maileater.net> wrote: > Hmm. One issue is that we're using different meanings for "parameters". > I don't think of an object's translation and rotation, or even scale, as > parameters. They are transformations externally applied to the object. I > generally find it offensive to specify a position or rotation as part of > the definition of an object - just as in the real world, an object comes > from the factory, and *then* I position it where I want it. > > And mostly that mental model works well, but not for this algorithm. > > For this algorithm, the transformation, rotation, and scale have to be > done in the middle of the algorithm, neither applied to the objects before > the algorithm nor applied to the result afterward. > > The reason for that is that the algorithm depends on scaling the objects, > for which they must be at the origin, and then intersecting the objects, > which must be with them at their final positions. > > I agree that it's ugly, though perhaps for different reasons than you > think it is. > > It makes my head hurt. > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
DH
Daniel Harvey
Fri, Feb 17, 2023 2:17 AM

Adrian - I agree that the use of scale improves the packaging here - thanks
for the contribution - but in essence the concept is still the original
method that I presented: to vary the sizes of the two objects via a
circular parameter and use the hulls of neighboring intersections to
achieve the fillet. Ultimately that is the information I was trying to
share. Clearly I succeeded despite the limited/awkward implementation.

On Thu, Feb 16, 2023 at 5:44 PM Adrian Mariano avm4@cornell.edu wrote:

Really Daniel's original approach is limited and awkward because it
requires having parameterized modules that give the object at different
offsets.  This is not a normal situation, or perhaps even easy to
accomplish, for most nontrivial objects.  If we had a 3d offset(), or were
willing to wait for minkowski() we could do this without those kinds of
assumptions, though it would still require convexity.  (And if you're
using minkowski then maybe just use that for rounding.)  I personally
think my modified approach using scale is more interesting because it
doesn't require having these weird parameterized modules.  And if you say
that it's easy enough to do it for cube and cylinder, well, then you can
make a module with explicit "cube" and "cylinder" options.  Sphere too.

The true right answer is to have access to the geometry and implement an
approach based on the points from the geometry, like I have done in BOSL2
and like Sanjeev has also done.  Right now, though, there is no way to
access the points of geometry, so you need to be able to make your object
some other way, which is also limiting.  Another observation is that if we
had the bounding box and centroid of the objects that would be enough
information to make this method work, at least in many cases.

On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown <
openscad@jordan.maileater.net> wrote:

Hmm.  One issue is that we're using different meanings for "parameters".
I don't think of an object's translation and rotation, or even scale, as
parameters.  They are transformations externally applied to the object.  I
generally find it offensive to specify a position or rotation as part of
the definition of an object - just as in the real world, an object comes
from the factory, and then I position it where I want it.

And mostly that mental model works well, but not for this algorithm.

For this algorithm, the transformation, rotation, and scale have to be
done in the middle of the algorithm, neither applied to the objects before
the algorithm nor applied to the result afterward.

The reason for that is that the algorithm depends on scaling the objects,
for which they must be at the origin, and then intersecting the objects,
which must be with them at their final positions.

I agree that it's ugly, though perhaps for different reasons than you
think it is.

It makes my head hurt.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Adrian - I agree that the use of scale improves the packaging here - thanks for the contribution - but in essence the concept is still the original method that I presented: to vary the sizes of the two objects via a circular parameter and use the hulls of neighboring intersections to achieve the fillet. Ultimately that is the information I was trying to share. Clearly I succeeded despite the limited/awkward implementation. On Thu, Feb 16, 2023 at 5:44 PM Adrian Mariano <avm4@cornell.edu> wrote: > Really Daniel's original approach is limited and awkward because it > requires having parameterized modules that give the object at different > offsets. This is not a normal situation, or perhaps even easy to > accomplish, for most nontrivial objects. If we had a 3d offset(), or were > willing to wait for minkowski() we could do this without those kinds of > assumptions, though it would still require convexity. (And if you're > using minkowski then maybe just use that for rounding.) I personally > think my modified approach using scale is more interesting because it > doesn't require having these weird parameterized modules. And if you say > that it's easy enough to do it for cube and cylinder, well, then you can > make a module with explicit "cube" and "cylinder" options. Sphere too. > > The true right answer is to have access to the geometry and implement an > approach based on the points from the geometry, like I have done in BOSL2 > and like Sanjeev has also done. Right now, though, there is no way to > access the points of geometry, so you need to be able to make your object > some other way, which is also limiting. Another observation is that if we > had the bounding box and centroid of the objects that would be enough > information to make this method work, at least in many cases. > > > On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown < > openscad@jordan.maileater.net> wrote: > >> Hmm. One issue is that we're using different meanings for "parameters". >> I don't think of an object's translation and rotation, or even scale, as >> parameters. They are transformations externally applied to the object. I >> generally find it offensive to specify a position or rotation as part of >> the definition of an object - just as in the real world, an object comes >> from the factory, and *then* I position it where I want it. >> >> And mostly that mental model works well, but not for this algorithm. >> >> For this algorithm, the transformation, rotation, and scale have to be >> done in the middle of the algorithm, neither applied to the objects before >> the algorithm nor applied to the result afterward. >> >> The reason for that is that the algorithm depends on scaling the objects, >> for which they must be at the origin, and then intersecting the objects, >> which must be with them at their final positions. >> >> I agree that it's ugly, though perhaps for different reasons than you >> think it is. >> >> It makes my head hurt. >> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Fri, Feb 17, 2023 2:44 AM

The method was very clear in your original implementation.  One could argue
that my approach obscures it somewhat.  The problem with scale is that it
may introduce distortion, and of course it makes things more complex with
positioning.  Another idea that would work for prisms and cones would be to
use offset() on the 2d shape that is extruded.  But that doesn't get away
from the problem of having to do positioning after the fact.

On Thu, Feb 16, 2023 at 9:18 PM Daniel Harvey dwaharvey@gmail.com wrote:

Adrian - I agree that the use of scale improves the packaging here -
thanks for the contribution - but in essence the concept is still the
original method that I presented: to vary the sizes of the two objects via
a circular parameter and use the hulls of neighboring intersections to
achieve the fillet. Ultimately that is the information I was trying to
share. Clearly I succeeded despite the limited/awkward implementation.

On Thu, Feb 16, 2023 at 5:44 PM Adrian Mariano avm4@cornell.edu wrote:

Really Daniel's original approach is limited and awkward because it
requires having parameterized modules that give the object at different
offsets.  This is not a normal situation, or perhaps even easy to
accomplish, for most nontrivial objects.  If we had a 3d offset(), or were
willing to wait for minkowski() we could do this without those kinds of
assumptions, though it would still require convexity.  (And if you're
using minkowski then maybe just use that for rounding.)  I personally
think my modified approach using scale is more interesting because it
doesn't require having these weird parameterized modules.  And if you say
that it's easy enough to do it for cube and cylinder, well, then you can
make a module with explicit "cube" and "cylinder" options.  Sphere too.

The true right answer is to have access to the geometry and implement an
approach based on the points from the geometry, like I have done in BOSL2
and like Sanjeev has also done.  Right now, though, there is no way to
access the points of geometry, so you need to be able to make your object
some other way, which is also limiting.  Another observation is that if we
had the bounding box and centroid of the objects that would be enough
information to make this method work, at least in many cases.

On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown <
openscad@jordan.maileater.net> wrote:

Hmm.  One issue is that we're using different meanings for
"parameters".  I don't think of an object's translation and rotation, or
even scale, as parameters.  They are transformations externally applied to
the object.  I generally find it offensive to specify a position or
rotation as part of the definition of an object - just as in the real
world, an object comes from the factory, and then I position it where I
want it.

And mostly that mental model works well, but not for this algorithm.

For this algorithm, the transformation, rotation, and scale have to be
done in the middle of the algorithm, neither applied to the objects before
the algorithm nor applied to the result afterward.

The reason for that is that the algorithm depends on scaling the
objects, for which they must be at the origin, and then intersecting the
objects, which must be with them at their final positions.

I agree that it's ugly, though perhaps for different reasons than you
think it is.

It makes my head hurt.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

The method was very clear in your original implementation. One could argue that my approach obscures it somewhat. The problem with scale is that it may introduce distortion, and of course it makes things more complex with positioning. Another idea that would work for prisms and cones would be to use offset() on the 2d shape that is extruded. But that doesn't get away from the problem of having to do positioning after the fact. On Thu, Feb 16, 2023 at 9:18 PM Daniel Harvey <dwaharvey@gmail.com> wrote: > Adrian - I agree that the use of scale improves the packaging here - > thanks for the contribution - but in essence the concept is still the > original method that I presented: to vary the sizes of the two objects via > a circular parameter and use the hulls of neighboring intersections to > achieve the fillet. Ultimately that is the information I was trying to > share. Clearly I succeeded despite the limited/awkward implementation. > > On Thu, Feb 16, 2023 at 5:44 PM Adrian Mariano <avm4@cornell.edu> wrote: > >> Really Daniel's original approach is limited and awkward because it >> requires having parameterized modules that give the object at different >> offsets. This is not a normal situation, or perhaps even easy to >> accomplish, for most nontrivial objects. If we had a 3d offset(), or were >> willing to wait for minkowski() we could do this without those kinds of >> assumptions, though it would still require convexity. (And if you're >> using minkowski then maybe just use that for rounding.) I personally >> think my modified approach using scale is more interesting because it >> doesn't require having these weird parameterized modules. And if you say >> that it's easy enough to do it for cube and cylinder, well, then you can >> make a module with explicit "cube" and "cylinder" options. Sphere too. >> >> The true right answer is to have access to the geometry and implement an >> approach based on the points from the geometry, like I have done in BOSL2 >> and like Sanjeev has also done. Right now, though, there is no way to >> access the points of geometry, so you need to be able to make your object >> some other way, which is also limiting. Another observation is that if we >> had the bounding box and centroid of the objects that would be enough >> information to make this method work, at least in many cases. >> >> >> On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown < >> openscad@jordan.maileater.net> wrote: >> >>> Hmm. One issue is that we're using different meanings for >>> "parameters". I don't think of an object's translation and rotation, or >>> even scale, as parameters. They are transformations externally applied to >>> the object. I generally find it offensive to specify a position or >>> rotation as part of the definition of an object - just as in the real >>> world, an object comes from the factory, and *then* I position it where I >>> want it. >>> >>> And mostly that mental model works well, but not for this algorithm. >>> >>> For this algorithm, the transformation, rotation, and scale have to be >>> done in the middle of the algorithm, neither applied to the objects before >>> the algorithm nor applied to the result afterward. >>> >>> The reason for that is that the algorithm depends on scaling the >>> objects, for which they must be at the origin, and then intersecting the >>> objects, which must be with them at their final positions. >>> >>> I agree that it's ugly, though perhaps for different reasons than you >>> think it is. >>> >>> It makes my head hurt. >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
SP
Sanjeev Prabhakar
Thu, Mar 9, 2023 1:00 AM

complex filleting done with the application of method proposed by Daniel,
although this creates zagged lines as hull cannot be applied due to the
concave shape of the original parts.

I think this is possible only if you can offset the 3d parts at their
locations.

it takes around 140 sec in my computer as the offset function is a little
slower in python it seems (90 offsets of each part are computed). File size
becomes 6.2 mb

this file can be downloaded from here:
https://github.com/sprabhakar2006/openSCAD/blob/main/very%20complex%20filleting.scad

[image: Screenshot 2023-03-09 at 6.14.15 AM.png]

On Fri, 17 Feb 2023 at 08:16, Adrian Mariano avm4@cornell.edu wrote:

The method was very clear in your original implementation.  One could
argue that my approach obscures it somewhat.  The problem with scale is
that it may introduce distortion, and of course it makes things more
complex with positioning.  Another idea that would work for prisms and
cones would be to use offset() on the 2d shape that is extruded.  But that
doesn't get away from the problem of having to do positioning after the
fact.

On Thu, Feb 16, 2023 at 9:18 PM Daniel Harvey dwaharvey@gmail.com wrote:

Adrian - I agree that the use of scale improves the packaging here -
thanks for the contribution - but in essence the concept is still the
original method that I presented: to vary the sizes of the two objects via
a circular parameter and use the hulls of neighboring intersections to
achieve the fillet. Ultimately that is the information I was trying to
share. Clearly I succeeded despite the limited/awkward implementation.

On Thu, Feb 16, 2023 at 5:44 PM Adrian Mariano avm4@cornell.edu wrote:

Really Daniel's original approach is limited and awkward because it
requires having parameterized modules that give the object at different
offsets.  This is not a normal situation, or perhaps even easy to
accomplish, for most nontrivial objects.  If we had a 3d offset(), or were
willing to wait for minkowski() we could do this without those kinds of
assumptions, though it would still require convexity.  (And if you're
using minkowski then maybe just use that for rounding.)  I personally
think my modified approach using scale is more interesting because it
doesn't require having these weird parameterized modules.  And if you say
that it's easy enough to do it for cube and cylinder, well, then you can
make a module with explicit "cube" and "cylinder" options.  Sphere too.

The true right answer is to have access to the geometry and implement an
approach based on the points from the geometry, like I have done in BOSL2
and like Sanjeev has also done.  Right now, though, there is no way to
access the points of geometry, so you need to be able to make your object
some other way, which is also limiting.  Another observation is that if we
had the bounding box and centroid of the objects that would be enough
information to make this method work, at least in many cases.

On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown <
openscad@jordan.maileater.net> wrote:

Hmm.  One issue is that we're using different meanings for
"parameters".  I don't think of an object's translation and rotation, or
even scale, as parameters.  They are transformations externally applied to
the object.  I generally find it offensive to specify a position or
rotation as part of the definition of an object - just as in the real
world, an object comes from the factory, and then I position it where I
want it.

And mostly that mental model works well, but not for this algorithm.

For this algorithm, the transformation, rotation, and scale have to be
done in the middle of the algorithm, neither applied to the objects before
the algorithm nor applied to the result afterward.

The reason for that is that the algorithm depends on scaling the
objects, for which they must be at the origin, and then intersecting the
objects, which must be with them at their final positions.

I agree that it's ugly, though perhaps for different reasons than you
think it is.

It makes my head hurt.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

complex filleting done with the application of method proposed by Daniel, although this creates zagged lines as hull cannot be applied due to the concave shape of the original parts. I think this is possible only if you can offset the 3d parts at their locations. it takes around 140 sec in my computer as the offset function is a little slower in python it seems (90 offsets of each part are computed). File size becomes 6.2 mb this file can be downloaded from here: https://github.com/sprabhakar2006/openSCAD/blob/main/very%20complex%20filleting.scad [image: Screenshot 2023-03-09 at 6.14.15 AM.png] On Fri, 17 Feb 2023 at 08:16, Adrian Mariano <avm4@cornell.edu> wrote: > The method was very clear in your original implementation. One could > argue that my approach obscures it somewhat. The problem with scale is > that it may introduce distortion, and of course it makes things more > complex with positioning. Another idea that would work for prisms and > cones would be to use offset() on the 2d shape that is extruded. But that > doesn't get away from the problem of having to do positioning after the > fact. > > On Thu, Feb 16, 2023 at 9:18 PM Daniel Harvey <dwaharvey@gmail.com> wrote: > >> Adrian - I agree that the use of scale improves the packaging here - >> thanks for the contribution - but in essence the concept is still the >> original method that I presented: to vary the sizes of the two objects via >> a circular parameter and use the hulls of neighboring intersections to >> achieve the fillet. Ultimately that is the information I was trying to >> share. Clearly I succeeded despite the limited/awkward implementation. >> >> On Thu, Feb 16, 2023 at 5:44 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >>> Really Daniel's original approach is limited and awkward because it >>> requires having parameterized modules that give the object at different >>> offsets. This is not a normal situation, or perhaps even easy to >>> accomplish, for most nontrivial objects. If we had a 3d offset(), or were >>> willing to wait for minkowski() we could do this without those kinds of >>> assumptions, though it would still require convexity. (And if you're >>> using minkowski then maybe just use that for rounding.) I personally >>> think my modified approach using scale is more interesting because it >>> doesn't require having these weird parameterized modules. And if you say >>> that it's easy enough to do it for cube and cylinder, well, then you can >>> make a module with explicit "cube" and "cylinder" options. Sphere too. >>> >>> The true right answer is to have access to the geometry and implement an >>> approach based on the points from the geometry, like I have done in BOSL2 >>> and like Sanjeev has also done. Right now, though, there is no way to >>> access the points of geometry, so you need to be able to make your object >>> some other way, which is also limiting. Another observation is that if we >>> had the bounding box and centroid of the objects that would be enough >>> information to make this method work, at least in many cases. >>> >>> >>> On Thu, Feb 16, 2023 at 12:56 PM Jordan Brown < >>> openscad@jordan.maileater.net> wrote: >>> >>>> Hmm. One issue is that we're using different meanings for >>>> "parameters". I don't think of an object's translation and rotation, or >>>> even scale, as parameters. They are transformations externally applied to >>>> the object. I generally find it offensive to specify a position or >>>> rotation as part of the definition of an object - just as in the real >>>> world, an object comes from the factory, and *then* I position it where I >>>> want it. >>>> >>>> And mostly that mental model works well, but not for this algorithm. >>>> >>>> For this algorithm, the transformation, rotation, and scale have to be >>>> done in the middle of the algorithm, neither applied to the objects before >>>> the algorithm nor applied to the result afterward. >>>> >>>> The reason for that is that the algorithm depends on scaling the >>>> objects, for which they must be at the origin, and then intersecting the >>>> objects, which must be with them at their final positions. >>>> >>>> I agree that it's ugly, though perhaps for different reasons than you >>>> think it is. >>>> >>>> It makes my head hurt. >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
MH
Martin Herdieckerhoff
Sat, Mar 11, 2023 2:54 PM

Am 17.02.2023 um 01:44 schrieb Adrian Mariano:

The true right answer is to have access to the geometry and implement
an approach based on the points from the geometry, like I have done in
BOSL2 and like Sanjeev has also done.

You relate to join_prism which is really amazing.
Indeed join_prism might be easily generalized a little further
to providing a fillet between two vertex arrays as can be passed to
vnf_vertex_array.

Assuming a vertex array comes from a Bezier-patch, the fillet could be
computed
even directly from the control points without computing the related
vertex array.

Similarly, when the surfaces can be described by two functions in two
scalar parameters -
as is easy e.g. for plane, cylinder, sphere, Bezier-patches and many more -
then the fillet can be provided directly from those functions with
basically the same methods.
Such functions could be passed as arguments to a function which makes
the fillet.

Fillets between arbitrary VNFs seem theoretically possible too but these
might present surprises and also be prohibitive with respect to speed.

Am 17.02.2023 um 01:44 schrieb Adrian Mariano: > The true right answer is to have access to the geometry and implement > an approach based on the points from the geometry, like I have done in > BOSL2 and like Sanjeev has also done. You relate to join_prism which is really amazing. Indeed join_prism might be easily generalized a little further to providing a fillet between two vertex arrays as can be passed to vnf_vertex_array. Assuming a vertex array comes from a Bezier-patch, the fillet could be computed even directly from the control points without computing the related vertex array. Similarly, when the surfaces can be described by two functions in two scalar parameters - as is easy e.g. for plane, cylinder, sphere, Bezier-patches and many more - then the fillet can be provided directly from those functions with basically the same methods. Such functions could be passed as arguments to a function which makes the fillet. Fillets between arbitrary VNFs seem theoretically possible too but these might present surprises and also be prohibitive with respect to speed.