sgenoud / replicad

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

Exception in intersectBlueprints #58

Closed paulftw closed 1 year ago

paulftw commented 1 year ago

intersectBlueprints throws Cannot read properties of undefined (reading 'length'). Input blueprints seem sane to me.

online demo

import { BlueprintSketcher, fuse2D, intersectBlueprints } from 'replicad'

const triangles = [
  [
    [-15, -10],
    [4.22649730810374, 7.5],
    [-15, 30],
  ],
  [
    [-15, 30],
    [4.22649730810374, 7.5],
    [4.226497308103742, 30],
  ],
  [
    [7.690598923241496, 30],
    [7.690598923241495, 7.5],
    [15, 30],
  ],
  [
    [4.22649730810374, 7.5],
    [15, -10],
    [7.690598923241495, 7.5],
  ],
  [
    [-15, -10],
    [15, -10],
    [4.22649730810374, 7.5],
  ],
  [
    [7.690598923241495, 7.5],
    [15, -10],
    [15, 30],
  ],
]

const triangles2 = [
  [
    [9.999999999999996, 7.5],
    [-15, 30],
    [-15, -10],
  ],
  [
    [9.999999999999996, 7.5],
    [10, 30],
    [-15, 30],
  ],
  [
    [13.46410161513775, 7.5],
    [15, 30],
    [13.464101615137752, 30],
  ],
  [
    [15, -10],
    [13.46410161513775, 7.5],
    [9.999999999999996, 7.5],
  ],
  [
    [15, -10],
    [9.999999999999996, 7.5],
    [-15, -10],
  ],
  [
    [15, -10],
    [15, 30],
    [13.46410161513775, 7.5],
  ],
]

const trianglesToBlueprint = triangles => {
  const blueprints = triangles.map(pts => {
    const bps = new BlueprintSketcher().movePointerTo(pts[0])
    pts.slice(1).forEach(p => bps.lineTo(p))
    return bps.close()
  })

  return blueprints.slice(1).reduce((acc, el) => fuse2D(acc, el), blueprints[0])
}

export function main() {
  const a = trianglesToBlueprint(triangles)
  const b = trianglesToBlueprint(triangles2)

  // return [
  //   a.sketchOnPlane('XY').extrude(1).translate(0, 0, 20),
  //   b.sketchOnPlane('XY').extrude(1).translate(0, 0, 30),
  // ]

  return intersectBlueprints(a, b).extrude(1).translate(0, 0, 50)
}
sgenoud commented 1 year ago

This pinpoints exactly why the Drawing abstraction is necessary. intersectBlueprints instersects two Blueprint object. But fuse2D returns a Blueprints object (with just one blueprint in it but you could fuse disjointed paths and have multiple blueprints).

I should tackle this: https://github.com/sgenoud/replicad/issues/46

Anyway, you can obtain what you want with:

  return intersectBlueprints(a.blueprints[0], b.blueprints[0])
    .sketchOnPlane()
    .extrude(1);
sgenoud commented 1 year ago

I have actually implemented #46 you can just replace new BlueprintSketcher().movePointerTo(pts[0]) by draw(pts[0]) and return a.intersect(b).

sgenoud commented 1 year ago

I think this has been fixed. You can have a look at an example here