Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unioning spheres ends up with too many polygons #5

Closed
danwinkler opened this issue Aug 6, 2014 · 3 comments
Closed

Unioning spheres ends up with too many polygons #5

danwinkler opened this issue Aug 6, 2014 · 3 comments

Comments

@danwinkler
Copy link

After unioning about 70 spheres together, I end up with a lot of polygons, as shown this image:

image

It also takes 5+ minutes to do all of the unions. Do you have any ideas on how to speed this up/clean up the end result? Thanks!

@miho
Copy link
Owner

miho commented Aug 6, 2014

What are you trying to do with so many spheres? :)

To reduce the runtime you can enable optimization. This is still a work in progress. But it should work in your case. For me it reduced the runtime to about 10-20 seconds.

Here's an example:

import eu.mihosoft.vrl.v3d.CSG;
import eu.mihosoft.vrl.v3d.FileUtil;
import eu.mihosoft.vrl.v3d.Sphere;
import eu.mihosoft.vrl.v3d.Transform;
import java.io.IOException;
import java.nio.file.Paths;

/**
 *
 * @author Michael Hoffer <info@michaelhoffer.de>
 */
public class Spheres {

    public CSG toCSG() {

        double maxR = 10;

        double w = 30;
        double h = 30;
        double d = 30;

        // optimization reduces runtime dramatically
        CSG.setDefaultOptType(CSG.OptType.POLYGON_BOUND);

        CSG spheres = null;

        for(int i = 0;i<70;i++) {
            CSG s = new Sphere(Math.random()*maxR).toCSG().
                    transformed(
                            Transform.unity().
                                    translate(
                                            Math.random()*w,
                                            Math.random()*h,
                                            Math.random()*d));
            if (spheres == null) {
                spheres = s;
            } else {
                spheres = spheres.union(s);
            }
        }

        return spheres;
    }

    public static void main(String[] args) throws IOException {
        FileUtil.write(Paths.get("spheres.stl"), new Spheres().toCSG().toStlString());
    }
}

@danwinkler
Copy link
Author

Thanks so much for the quick response, and for the example code! I'm really enjoying using JCSG so far, thank you for creating it.

Your fix worked great, the polygons are much cleaner and the operations are much faster:
image

A small bug appeared when I changed the OptType, but it's easy to work around for now.

When I tried to subtract a cube from the spheres that wasn't intersecting with the spheres, I got this error:

Exception in thread "main" java.lang.RuntimeException: Please fix me! I don't know what to do?
    at eu.mihosoft.vrl.v3d.Node.invert(Node.java:133)
    at eu.mihosoft.vrl.v3d.CSG._differenceNoOpt(CSG.java:560)
    at eu.mihosoft.vrl.v3d.CSG._differencePolygonBoundsOpt(CSG.java:550)
    at eu.mihosoft.vrl.v3d.CSG.difference(CSG.java:517)
    at Spheres.toCSG(Spheres.java:50)
    at Spheres.main(Spheres.java:56)

I recreated the error by modifying your example code. Replace the Spheres.toCSG with:

    public CSG toCSG() {

        double maxR = 10;

        double w = 30;
        double h = 30;
        double d = 30;

        // optimization reduces runtime dramatically
        CSG.setDefaultOptType(CSG.OptType.POLYGON_BOUND);

        CSG spheres = null;

        for(int i = 0;i<20;i++) {
            System.out.println( "s " + i );
            CSG s = new Sphere(Math.random()*maxR).toCSG().
                transformed(
                    Transform.unity().
                        translate(
                            Math.random()*w - (w/2),
                            Math.random()*h - (h/2),
                            Math.random()*d - (d/2)
                        ));
            if (spheres == null) {
                spheres = s;
            } else {
                spheres = spheres.union(s);
            }
        }

        CSG box = new Cube( 100, 100, 100 ).toCSG().transformed( Transform.unity().translate( 0, 0, -110 ) );

        spheres = spheres.difference( box );

        return spheres;
    }

Like I said, pretty easy to work around for now. Thanks again!

@danwinkler
Copy link
Author

Oh, and the reason I'm trying to union so many spheres is for 3D Printing. I was trying to recreate what I did using OpenSCAD:
3DPrint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants