// Return a new CSG solid representing space in either this solid or in the
        // solid `csg`. Neither this solid nor the solid `csg` are modified.
        public static csgjs_csgnode csg_union(csgjs_csgnode a1, csgjs_csgnode b1)
        {
            csgjs_csgnode a = a1.clone();
            csgjs_csgnode b = b1.clone();

            a.clipTo(b);
            b.clipTo(a);
            b.invert();
            b.clipTo(a);
            b.invert();
            a.build(b.allPolygons());
            csgjs_csgnode ret = new csgjs_csgnode(a.allPolygons());

            a = null;
            b = null;
            return(ret);
        }
        // Build a BSP tree out of `polygons`. When called on an existing tree, the
        // new polygons are filtered down to the bottom of the tree and become new
        // nodes there. Each set of polygons is partitioned using the first polygon
        // (no heuristic is used to pick a good split).
        void build(List <csgjs_polygon> list)
        {
            if (list.Count == 0)
            {
                return;
            }

            if (!plane.ok())
            {
                plane = list[0].plane;
            }

            List <csgjs_polygon> list_front = new List <csgjs_polygon>();
            List <csgjs_polygon> list_back  = new List <csgjs_polygon>();

            for (int i = 0; i < list.Count; i++)
            {
                plane.splitPolygon(list[i], polygons, polygons, ref list_front, ref list_back);
            }
            if (list_front.Count > 0)
            {
                if (front == null)
                {
                    front = new csgjs_csgnode();
                }

                front.build(list_front);
            }
            if (list_back.Count > 0)
            {
                if (back == null)
                {
                    back = new csgjs_csgnode();
                }

                back.build(list_back);
            }
        }