AllwineDesigns / stl_cmd

stl_cmd - commands for binary STL file manipulation
Other
50 stars 9 forks source link

incorrect difference in stl_boolean? #10

Closed SebKuzminsky closed 10 months ago

SebKuzminsky commented 11 months ago

Hi @jallwine, i'm runing in to what i think is a bug in stl_boolean, current tip of master (0368b865cf531981cafcf53f3232bbe91d65252a).

I'm trying to use these tools to visualize changes between versions of a 3d model i'm working on. So i pull the old and new versions out of git and compute the diff between them with stl_boolean -d.

I've attached my two input files and the output of stl_boolean -a a.stl -b b.stl -d diff.stl (as a zip file, because github won't let me attach stl...).

Here are some screenshots of the STL viewer fstl which hopefully will show what i'm talking about.

Here's an overview of what both parts look like: Screenshot from 2023-10-17 21-11-25

Zooming in on the little "knob" under the "window" in the upper left of the picture we see the change i made. Here's the old one, "a.stl", notice the gap between the knob and the wall: Screenshot from 2023-10-17 21-12-05

Here's the new one, "b.stl", with the gap filled in: Screenshot from 2023-10-17 21-12-42

So the diff should be a rectangular chunk measuring about 14 mm in the X direction, 0.5 mm in Y, and 10mm in Z. But here's the diff from stl_boolean: Screenshot from 2023-10-17 21-13-22 Screenshot from 2023-10-17 21-13-12

And the bounding box of the diff is way off:

$ stl_bbox diff.stl 
File: diff.stl Extents: (4.624752, 36.662292, 0.971429) - (4.820009, 36.839779, 1.142857)
File: diff.stl Dimensions: (0.195257, 0.177486, 0.171429)

I don't know the first thing about stl_cmd, but is this possibly related to #2?

I'm happy to run any experiments you think would be helpful, but I probably can't contribute much beyond that...

stls.zip

jallwine commented 11 months ago

stl_boolean is certainly the most finicky of the stl_cmds. I attempted to port CSG.js and never really finished. That said, it sounds like from your description that you want b minus a. Difference in this context is subtraction rather than a general comparison so the order matters. What happens when you switch the arguments around?

jallwine commented 11 months ago

I just tried it and got something that seems reasonable:

stl_boolean -a b.stl -b a.stl -d out.stl
stl_bbox out.stl

Extents: (4.790240, 40.115547, -8.000000) - (25.000000, 67.500000, 1.142857)
Dimensions: (20.209759, 27.384453, 9.142858)

Looking at it in Blender also seems right.

Screen Shot 2023-10-18 at 9 11 10 AM
SebKuzminsky commented 11 months ago

Interesting, stl_boolean -a b.stl -b a.stl -d diff-ba.stl gives much better results (even though i'd expect this operation to be symmetrical): Screenshot from 2023-10-18 09-07-32

The "diff these stls" process i'm actually trying to develop is this:

The example in the original post above was just the simplest reproduction i could make of the issue i was seeing.

jallwine commented 11 months ago

I think you just need:

deleted: stl_boolean -a old.stl -b new.stl -d deleted.stl added: stl_boolean -a new.stl -b old.stl -d added.stl

jallwine commented 11 months ago

It's not unusual, though, for small volume differences to exist. The original diff.stl file you sent over for example, is a tiny number of faces not anywhere near where you thought your differences were.

Screen Shot 2023-10-18 at 9 24 10 AM
jallwine commented 11 months ago

A similar set of surfaces exists in the diff I sent over, which is why the bbox is not what you expected. Once I remove the tiny extra faces, it shows the dimensions you expected:

Extents: (11.000000, 67.000000, -8.000000) - (25.000000, 67.500000, 0.000000)
Dimensions: (14.000000, 0.500000, 8.000000)
jallwine commented 11 months ago

I have an alias for stl_view that opens blender with any number of provided STL files which can be helpful to diagnose these things:

alias stl_view='blender --python load_stl.py --'

load_stl.py:

import bpy
import sys

# run with:
# blender --python /path/to/this/script/load_stl.py -- <any number of STL files>

# I like to alias it to stl_view in my bashrc file:
# alias stl_view='blender --python /path/to/this/script/load_stl.py --'

try:
  index = sys.argv.index("--")

  files = sys.argv[index+1:len(sys.argv)]
  for file in files:
    bpy.ops.import_mesh.stl(filepath=file)

  for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
      args = { 'area': area, 'region': area.regions[-1] }
      bpy.ops.view3d.view_all(args)

except:
  pass
SebKuzminsky commented 10 months ago

I think you just need:

deleted: stl_boolean -a old.stl -b new.stl -d deleted.stl added: stl_boolean -a new.stl -b old.stl -d added.stl

I must not understand what "difference" means here - i had assumed it meant "everything except for the intersection", but this makes it sound like it means "everything that's in a but not in b" (i.e., it does not include the stuff that's in b but not a). Is that right? If so then yeah that gets me moving again.

Thanks @jallwine!

jallwine commented 10 months ago

Correct, "everything that's in a but not in b". The CSG.js docs have a good visualization: https://evanw.github.io/csg.js/

SebKuzminsky commented 10 months ago

Ok! Thanks for applying the clue-bat :-)

SebKuzminsky commented 10 months ago

Ah, i see the terminology changed from a.subtract(b) in CSG.js to difference of A and B in stl_cmd, i think that's where my confusion came from.

a.subtract(b) reads pretty clearly as "everything that's in a, except for b".

difference of A and B reads to me as "everything in A or B, except for their intersection".

But i may be reading that wrong, what do words even mean? :-)