SolidCode / SolidPython

A python frontend for solid modelling that compiles to OpenSCAD
1.11k stars 173 forks source link

small fix for multiple subtracting holes #73

Closed scifuentes closed 7 years ago

scifuentes commented 7 years ago

When two or more holes are subtracted from a initial solid, only the first hole have any effect. The proposed fix enforces that holes are added as unions and not as differences.

test code:

scene = ( cube([10,10,1],center=True)
          - cylinder().set_hole()
          - translate([3,0,0])(cylinder()).set_hole()
        )
scad_render_to_file(scene, 'preview.scad', '$fs=.75;')

The current render will show a single hole since the second hole is subtracted from the first and they do not overlap:

difference(){
    difference() {
        difference() {
            cube(center = true, size = [10, 10, 1]);
        }
    }
    /* Holes Below*/
    difference(){
        difference(){
            cylinder();
        }
        translate(v = [3, 0, 0]) {
            cylinder();
        }
    } /* End Holes */ 
}

The render with the proposed fix will show the two holes as expected:

difference(){
    union() {
        union() {
            cube(center = true, size = [10, 10, 1]);
        }
    }
    /* Holes Below*/
    union(){
        union(){
            cylinder();
        }
        translate(v = [3, 0, 0]) {
            cylinder();
        }
    } /* End Holes */ 
}

Only elements labeled as holes are forced as unions, this will not affect the inner structure of the holes objects, so if the hole solid is created using a difference this will be kept. The next will work as expected, where the third hole will be a 3/4 of cylinder shape:

scene = ( cube([10,10,1],center=True)
          - cylinder().set_hole()
          - translate([3,0,0])(cylinder()).set_hole()
          - translate([-3,0,0])(cylinder()-cube()).set_hole()
        )
etjones commented 7 years ago

Just now taking a look at this, @scifuentes. I definitely want to solve this issue-- if a hole doesn't show up as a hole, the feature's broken-- but I suspect this is an error in my original logic here. If we can resolve the problem there rather than explicitly in the difference() method, I'd prefer to. Let me see if I can get the issue clear in my head and fix this at the source of the problem

etjones commented 7 years ago

Found a solution to this in solidpython._render_hole_children() that I think gets to the heart of the issue. #80 yields the correct shape from your example, although the nested operations are slightly different:

$fs=.75;

difference(){
    difference() {
        cube(center = true, size = [10, 10, 1]);
    }
    /* Holes Below*/
    union(){
        cylinder();
        translate(v = [3, 0, 0]) {
            cylinder();
        }
    } /* End Holes */ 
}