jscad / OpenJSCAD.org

JSCAD is an open source set of modular, browser and command line tools for creating parametric 2D and 3D designs with JavaScript code. It provides a quick, precise and reproducible method for generating 3D models, and is especially useful for 3D printing applications.
https://openjscad.xyz/
MIT License
2.58k stars 505 forks source link

trying to extrude an SVG ends up with weird non-solid object that behaves unexpectedly #1253

Open tsdexter opened 1 year ago

tsdexter commented 1 year ago

Expected Behavior

I expect to see a solid 'f'

Actual Behavior

The object that is extruded from the SVG looks like it's not solid, has no top face: image

However, when I rotate the viewport around, for example, to look at it from underneath then is appears there is a top surface: image

When I subtract the extruded SVG from a cube, it behaves strangely, looks more like an intersection of the two:

Cube and 'f' with no subtraction: image

Result of subtract(cube({ size: 10 }), extrudedSvg): image

Even a basic path to create a square results in this behaviour (comment out line 13 to reproduce): image

Steps to Reproduce the Problem

https://codesandbox.io/s/jscad-react-js-demo-forked-7soe65?file=/src/App.js

Specifications

see codesandbox

tsdexter commented 1 year ago

I also tried testing this directly on openjscad.xyz but I get:

SyntaxError: Cannot find module @jscad/svg-deserializer

How do I load serializers into openjscad.xyz?

z3dev commented 1 year ago

@tsdexter see #1087 which discusses the issues with SVG. Hopefully, you will find a few hints.

tsdexter commented 1 year ago

@z3dev thanks, I did see that and was hoping it wasn't related... Going back for a closer look, I was able to get some working extrusions by inverting them all and then knowingly combining specific entries in the returned array via intersect like:

union(solids[0], intersect(solids[1], solids[2]), solids[3], intersect(solids[4], solids[5]))

I had to know which indexes were holes on which solids. However, I am doing this on dynamic/generated SVG paths, so this is not ideal. Is there any plans to improve the SVG importing in the near future?

platypii commented 1 year ago

Is there any plans to improve the SVG importing in the near future?

I would REALLY like to see SVG import fixed. I just have not had time to dig in. PRs are welcome :-)

tsdexter commented 1 year ago

@platypii in the interest of time, I am using a workaround for now (mapping indices to holes/solids for the known possible paths that will be generated).

So far, I like what I'm seeing with OpenJSCAD, I think it will be very useful for what I'm working on. I will definitely look to contribute (starting with SVG imports!), time permitting :)

platypii commented 1 year ago

I think it might not actually be that hard to fix. I'm not sure it works for all cases, but concatenating the sides together and making a single new geom2 object, instead of returning a list of separate objects, seems to work even for nested holes:

const { extrusions } = require('@jscad/modeling')
const { deserializers } = require('@jscad/io')

const main = () => {
  // parse svg
  const svgText = `
  <svg>
    <path d="m3 9h6v-6h-6v6zm1-5h4v4h-4v-4zm-4 8h12v-12h-12v12zm1-11h10v10h-10v-10" fill="#000"/>
  </svg>`
  const svg = deserializers.svg({ output: "geometry", target: "geom2"}, svgText)

  // concatenate all sides together
  const fixed = {
    ...svg[0],
    sides: svg.reduce((acc, obj) => acc.concat(obj.sides), [])
  }

  // extrude
  return extrusions.extrudeLinear({ height: 1 }, fixed)
}

module.exports = { main }

svg-extr