/// <summary> /// Populate the Subdivision member with a spatial hierarchical structure that helps locate an extreme vertex in /// log(Vertices_Number) steps /// /// The arguments that start the recursion should be (0 ,total_vertices) and correspond to polygon edge normals /// that define a sub-piece of the unit disc /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> private Polygon_Tree_Node Subdivide(int start, int end) { bool is_subdivision_direction = true; //this is what will be returned upwards the recursion var node = new Polygon_Tree_Node(this); //this predicate means we've reached a node that is just supposed to add 2 vertex leaf nodes and return if (end - start == 1) { node.code = start; var left_vertex_node = new Polygon_Tree_Node(this); left_vertex_node.code = this.Vertex(end); node.link_l = left_vertex_node; var right_vertex_node = new Polygon_Tree_Node(this); right_vertex_node.code = this.Vertex(start); node.link_r = right_vertex_node; return node; } //in the recursion's main case we just find the middle normal in this subpiece of the unit disc // (the middle in the sense of the sequence defined by the polygon edges outwards normals starting // at the vertex 0 - vertex 1 edge and going ccw) // then recursively call the function on the 2 sub pieces defined by start,middle middle, end var middle = Helper.Middle(start, end); node.left_part_start_normal = start; node.left_part_end_normal = middle; node.right_part_end_normal = end; node.code = middle; node.link_l = Subdivide(start, middle); node.link_r = Subdivide(middle, end); node.division_direction = is_subdivision_direction; return node; }
/// <summary> /// Uses the specified points to initialize the polygon's data /// </summary> /// <param name="points_inserted"></param> public void Set(List<Vector3> points_inserted) { vertices_no = points_inserted.Count; if (points_inserted.Count < 3) throw new Exception("not enough points to make a polygon"); var winding = Vector3.Cross(points_inserted[0], points_inserted[1]).Z; if (winding < 0) for (int i = 0; i < points_inserted.Count; i++) points_inserted[i] = new Vector3(-points_inserted[i].X, points_inserted[i].Y, 0); Points.Clear(); Normals.Clear(); Angles.Clear(); for (int i = 0; i < points_inserted.Count; i++) { Points.Add(points_inserted[i]); } for (int i = 0; i < Points.Count - 1; i++) { var point1 = Points[i]; var point2 = Points[i + 1]; var vec = point2 - point1; var normal = Vector3.Cross(vec, Vector3.Backward); normal.Normalize(); Normals.Add(normal); } var point1_ = Points[Points.Count - 1]; var point2_ = Points[0]; var vec_ = point2_ - point1_; var normal_ = Vector3.Cross(vec_, Vector3.Backward); normal_.Normalize(); Normals.Add(normal_); var TwoPi = (float)(2 * Math.PI); var begin_angle = Helper.Get_Zero_Two_Pi_Angle(Normals[0]); Beginning_Normal_Angle = begin_angle; for (int i = 0; i < Normals.Count; i++) { var angle = Helper.Get_Zero_Two_Pi_Angle(Normals[i]); angle = Helper.Fix_Angle(angle, begin_angle); angle -= begin_angle; Angles.Add(angle); } Angles.Add(TwoPi); var res = Subdivide(0, vertices_no); this.Subdivision = res; }