}//End of Octree constructor //Constructor for creating nodes in the octree public Octree(Vertex bas, float width, List <int> indices, List <Triangle> triangles, int max_triangles, float min_width) { Vertex centre = bas.add(new Vertex(width, width, width).truediv(2f)); this.triangles = triangles; this.max_triangles = max_triangles; this.min_width = min_width; this.width_x /= 2f; this.width_y /= 2f; this.width_z /= 2f; this.base_width = KCLWriter.min(width_x, width_y, width_z); this.bas = new Vertex(width / 2f, width / 2f, width / 2f); foreach (int i in indices) { if (KCLWriter.tribox_overlap(this.triangles[i], centre, width / 2f)) { this.indices.Add(i); } } this.is_leaf = true; //Console.WriteLine("node hw: " + width / 2f + " num of indices: " + this.indices.Count); if (this.indices.Count > this.max_triangles && width >= (2 * this.min_width)) { for (int k = 0; k < 2; k++) { for (int j = 0; j < 2; j++) { for (int i = 0; i < 2; i++) { this.children.Add(new Octree(bas.add(new Vertex((float)i, (float)j, (float)k).truediv(2f).mul(width)), width / 2, this.indices, this.triangles, this.max_triangles, this.min_width)); } } } this.indices.Clear(); this.is_leaf = false; } }
//Base octree constructor public Octree(List <Triangle> triangles, int max_triangles, float min_width) { this.triangles = triangles; this.max_triangles = max_triangles; this.min_width = min_width; float min_x = 0, min_y = 0, min_z = 0, max_x = 0, max_y = 0, max_z = 0; foreach (Triangle t in triangles) { float min_x0 = KCLWriter.min(KCLWriter.min(t.u.x.theValue, t.v.x.theValue, t.w.x.theValue)); if (min_x0 < min_x) { min_x = min_x0; } float min_y0 = KCLWriter.min(KCLWriter.min(t.u.y.theValue, t.v.y.theValue, t.w.y.theValue)); if (min_y0 < min_y) { min_y = min_y0; } float min_z0 = KCLWriter.min(KCLWriter.min(t.u.z.theValue, t.v.z.theValue, t.w.z.theValue)); if (min_z0 < min_z) { min_z = min_z0; } float max_x0 = KCLWriter.max(KCLWriter.max(t.u.x.theValue, t.v.x.theValue, t.w.x.theValue)); if (max_x0 > max_x) { max_x = max_x0; } float max_y0 = KCLWriter.max(KCLWriter.max(t.u.y.theValue, t.v.y.theValue, t.w.y.theValue)); if (max_y0 > max_y) { max_y = max_y0; } float max_z0 = KCLWriter.max(KCLWriter.max(t.u.z.theValue, t.v.z.theValue, t.w.z.theValue)); if (max_z0 > max_z) { max_z = max_z0; } } // If model only uses two axes, eg. flat square, the base width will get set to min_width (1) which can // create an octree with 100's of thousands of tiny empty or almost empty nodes is very computationally expensive if (max_x == 0) { max_x = KCLWriter.max(max_y, max_z); } if (max_y == 0) { max_y = KCLWriter.max(max_x, max_z); } if (max_z == 0) { max_z = KCLWriter.max(max_x, max_y); } this.width_x = (float)Math.Pow(2, (int)(Math.Ceiling(Math.Log(KCLWriter.max(max_x - min_x, min_width), 2)))); this.width_y = (float)Math.Pow(2, (int)(Math.Ceiling(Math.Log(KCLWriter.max(max_y - min_y, min_width), 2)))); this.width_z = (float)Math.Pow(2, (int)(Math.Ceiling(Math.Log(KCLWriter.max(max_z - min_z, min_width), 2)))); this.base_width = KCLWriter.min(width_x, width_y, width_z); this.bas = new Vertex(min_x, min_y, min_z); this.nx = (int)Math.Floor(this.width_x / this.base_width); this.ny = (int)Math.Floor(this.width_y / this.base_width); this.nz = (int)Math.Floor(this.width_z / this.base_width); List <int> ind = new List <int>(); for (int i = 0; i < triangles.Count; i++) { ind.Add(i); } for (int k = 0; k < this.nz; k++) { for (int j = 0; j < this.ny; j++) { for (int i = 0; i < this.nx; i++) { this.children.Add(new Octree(this.bas.add((new Vertex(i, j, k)).mul(this.base_width)), this.base_width, ind, this.triangles, this.max_triangles, this.min_width)); } } } }//End of Octree constructor