sgenoud / replicad

The library to build browser based 3D models with code.
https://replicad.xyz
MIT License
323 stars 38 forks source link

Missing documentation on 3D operations #124

Closed maelp closed 5 months ago

maelp commented 6 months ago

I'm building some shapes by extruding, and then I'd like to combine them in a global object that I can export / texture / visualize in Three.js, but I don't know how to combine the extruded objects into a single combined object?

raydeleu commented 6 months ago

Perhaps this rough chapter of the manual for Replicad provides some ideas?

https://github.com/raydeleu/ReplicadManual/wiki/8.-Combine-solids-to-parts

If the parts are overlapping I would advise to use the .fuse method. An example is

let threeArm = arm1.fuse(arm2);
threeArm = threeArm.fuse(arm3).fillet(fl,(e)=>e.inDirection("Z"));

I have not used the functions compoundShapes(shapeArray[]) or makeCompound(shapeArray[]), but I assume you just add the shapes you want to combine into an array and then use the function on this array.

A quick test:

const {draw,makeBaseBox,makeCompound} = replicad

function main()
{
let length = 100;
let width = 50;
let height = 12;
let radius = 5;
let tolerance =0.001

let box1 = makeBaseBox(length,width,height)
let box2 = makeBaseBox(length,width,height).translate([150,0,0])

let compound;
compound = [{shape: box1},{shape: box2}]
compound = makeCompound([box1.clone(),box2.clone()])  // if you comment this line there are two shapes

return compound
}

If you remove the second definition of compound you will see two shapes in the Visualizer or Workbench, if you use the makeCompound statement the two shapes are considered to be a single entity.

maelp commented 6 months ago

Thanks! Hadn't seen that there was a manual!

maelp commented 6 months ago

@raydeleu hmmmm doesn't seem to work the way I want, I'm trying to do something like this:

const cellPositions=[{x:0, y:0}, {x: 0, y: 1}, ...];
const renderCell = () => {
  return drawPolysides(1.0, 6).sketchOnPlane('XZ').extrude(5.0);
}
export const createCompound = () => {
  const cells = cellPositions.map((p) => {
    const cell = renderCell(data);
    cell.translate(p.x, 0, p.y);
    return cell;
  });
  const compound = // ???? an object containing all the hexagon cylinders
  return compound;
};
maelp commented 6 months ago

And when I try using

const renderCell = (data: RenderData) => {
  return sketchPolysides(data.cellDiameterM / 2.0, 6, 0, { plane: 'XZ' }).extrude(data.cellLengthM);
}

and

  const cells = data.cellPositions.map((p) => {
    const cell = renderCell(data);
    cell.translate(p.x, 0, p.y);
    return cell;
  });
  let compound = cells[0];
  for (const cell of cells.slice(1)) {
    compound = compound.fuse(cell);
  }
  return compound;

there's an error in the browser saying:

Error: This object has been deleted
    at get wrapped [as wrapped] (replicad.js?v=94009da6:44:13)
    at Solid.fuse (replicad.js?v=94009da6:3052:43)
    at _createBatteryModelWorkerFn (cad-battery.ts:72:25)
    at :5173/src/lib/cad-worker.ts?type=module&worker_file:23:19
raydeleu commented 6 months ago

I was not able to understand your code completely (especially the cell of cells.slice(1) puzzles me) but my first impression is that you want to create a grid of hexagon shapes. I have seen the error message before and it always was due to the fact that Replicad deletes a shape once you have performed a function or method on it. The idea is to save memory on shapes that are no longer used. In some cases it helps to perform a method on a .clone() instead of the original shape. You can see the example in my code. It could be that in the statement compound = compound.fuse(cell) the shape cell is deleted.

maelp commented 6 months ago

Thanks, figured out how to do it (though I'm not sure why there was an error in my original code)

I'm wondering: the fuse operation is quite slow, is there a way to merge shapes together without doing the fuse ?

raydeleu commented 6 months ago

You could try the makeCompound() function. With fuse the kernel tries to calculate a boolean union of your shapes. If the shapes are not overlapping this is a useless calculation, yet takes time.