Skip to content

Bug: Kernel error when fuse()ing a straight cylinder with one made with genericSweep() #223

@danfuzz

Description

@danfuzz

[As with issue #221, this is presumably a bug in the underlying OpenCASCADE library, but I don't know how to translate my findings here to that level.]

I ran into a modeling issue where fusing a straight cylinder with a curved cylinder made from one created by genericSweep()ing will work when fusing via straightTube.fuse(curveTube) but not curveTube.fuse(straightTube). The latter causes a "kernel error."

I tried simplifying my test case as much as I could, and here's where I landed. You'll note that I'm making the straightTube in a bit of a convoluted way (extruding along the "wrong" axis and then rotating it into position), which is an artifact of the non-test-case that I started with. (I tried extruding it in a more straightforward way but was unable to reproduce the bug after that cleanup.)

const {
  assembleWire,
  drawCircle,
  genericSweep,
  makeCircle,
  makeLine,
  makeTangentArc
} = replicad;

const TUBE_RADIUS     = 20;
const STRAIGHT_LENGTH = 70;
const ARC_ARM_LENGTH  = 19;
const ARC_RADIUS      = 25;

const ARC_FULL_LENGTH = ARC_ARM_LENGTH + ARC_RADIUS;

function addPoints(point1, point2) {
  const [x1, y1, z1] = point1;
  const [x2, y2, z2] = point2;

  return [x1 + x2, y1 + y2, z1 + z2];
}

function makeStraightTube() {
  return drawCircle(TUBE_RADIUS)
    .sketchOnPlane('YZ')
    .extrude(STRAIGHT_LENGTH)
    .rotate(90);
}

function makeCurveTube() {
  // Note: `genericSweep()` gets confused if the `path` wire doesn't start at the origin.
  const arcStartPoint = [0, 0, 0];
  const arcTangentPoint = addPoints(arcStartPoint, [ARC_RADIUS, 0, 0]);
  const arcEndPoint     = addPoints(arcTangentPoint, [0, -ARC_RADIUS, 0]);
  const endPoint        = addPoints(arcEndPoint, [0, -ARC_ARM_LENGTH, 0]);

  const path = assembleWire([
    makeTangentArc(arcStartPoint, arcTangentPoint, arcEndPoint),
    makeLine(arcEndPoint, endPoint)
  ]);

  const section   = assembleWire([makeCircle(TUBE_RADIUS)]);
  const sweepOpts = { transitionMode: 'round' };
  const shape     = genericSweep(section, path, sweepOpts, false);

  // `translate()` to move the circle-center of the arc to the origin, and then
  // `rotate()` to put it in the x-z plane instead of the x-y plane.
  return shape
    .translate(-ARC_RADIUS, ARC_FULL_LENGTH, 0)
    .rotate(90, [0, 0, 0], [0, 1, 0]);
}

function main()
{
  const straightTube = makeStraightTube();
  const curveTube    = makeCurveTube();

  // Uncomment this to see a version that works.
  return straightTube.fuse(curveTube);

  return curveTube.fuse(straightTube);
}

For reference, here's what the shape looks like when correctly fused:

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions