// key difference between a static and a non-static method is that static method belongs to a class while non-static method belongs to the instance public static double angle_between(edge_store with_edge, edge_store the_edge) { double v1_x, v1_y; double v2_x, v2_y; double normalzie; // vector with edge v1_x = with_edge.end_pt.x - with_edge.start_pt.x; v1_y = with_edge.end_pt.y - with_edge.start_pt.y; normalzie = Math.Sqrt(Math.Pow(v1_x, 2) + Math.Pow(v1_y, 2)); v1_x = v1_x / normalzie; v1_y = v1_y / normalzie; // vector the edge v2_x = the_edge.end_pt.x - the_edge.start_pt.x; v2_y = the_edge.end_pt.y - the_edge.start_pt.y; normalzie = Math.Sqrt(Math.Pow(v2_x, 2) + Math.Pow(v2_y, 2)); v2_x = v2_x / normalzie; v2_y = v2_y / normalzie; // sin and cos of the two vectors double sin = (v1_x * v2_y) - (v2_x * v1_y); double cos = (v1_x * v2_x) + (v1_y * v2_y); double angle = (Math.Atan2(sin, cos) / Math.PI) * 180f; if (angle <= 0) // there is no zero degree (zero degree = 360 degree) to avoid the vertical line mismatch { angle += 360f; } return(angle); }
public edge_store find_intial_baseLR(List <point_store> left, List <point_store> right) { point_store left_end = left[left.Count - 1]; // left end // Colinear error fixed point_store right_end = right[0]; // right end edge_store left_bot_edge = left_end.cw_vertical_edge(0); // First Vertical edge at clock wise direction at this point edge_store right_bot_edge = right_end.cc_vertical_edge(0); // First Vertical edge at counter clock wise direction at this point while (true) { // Select the bottom most end by comparing the orientation with the other if (leftof(right_end, left_bot_edge) == true) // check the right_end point and orientation of the left edge { left_end = left_bot_edge.the_other_pt(left_end); // Find the next point (whihc is the endpoint of the left edge) left_bot_edge = left_end.cw_vertical_edge(0); } else if (rightof(left_end, right_bot_edge) == true) // check the left_end point and orientation of the right edge { right_end = right_bot_edge.the_other_pt(right_end); // Find the next point (which is the endpoint of the right edge) right_bot_edge = right_end.cc_vertical_edge(0); } else { break; } } add_edge(left_end, right_end); // Add the base LR edge return(edge_list[edge_list.Count - 1]); // return the last add item (which is the baseLR edge) }
private void add_to_local_list(edge_store e, triangle_store t) { //____________________________________________________________________________________________________________________________________________________________________ // !! Addition on main list here //Form1.planar_object_store.point2d spt = local_input_points.Find(obj => obj.Equals(new Form1.planar_object_store.point2d(e.start_pt.pt_id, e.start_pt.x, e.start_pt.y))); //Form1.planar_object_store.point2d ept = local_input_points.Find(obj => obj.Equals(new Form1.planar_object_store.point2d(-1, e.end_pt.x, e.end_pt.y))); Form1.planar_object_store.edge2d temp_edge = new Form1.planar_object_store.edge2d(e.edge_id, e.start_pt.get_parent_data_type, e.end_pt.get_parent_data_type); local_output_edges.Add(temp_edge); if (t != null) { Form1.planar_object_store.face2d temp_face = new Form1.planar_object_store.face2d(t.tri_id, t.p1.get_parent_data_type, t.p2.get_parent_data_type, t.p3.get_parent_data_type); local_output_triangle.Add(temp_face); } // ################################################################# Form1.planar_object_store.instance_tracker temp_edge_tracker = new Form1.planar_object_store.instance_tracker(); temp_edge_tracker.edge_list = new List <Form1.planar_object_store.edge2d>(); temp_edge_tracker.edge_list.AddRange(local_output_edges); temp_edge_tracker.face_list = new List <Form1.planar_object_store.face2d>(); temp_edge_tracker.face_list.AddRange(local_output_triangle); local_history_tracker.Add(temp_edge_tracker); // ################################################################# }
public bool Equals_without_orientation(edge_store other) { if ((other.Equals(this) == true) || (other.Equals(this.sym) == true)) { return(true); } return(false); }
public bool Equals(edge_store other) { if (other.start_pt.Equals(this._start_pt) == true && other.end_pt.Equals(this._end_pt) == true) { return(true); } return(false); }
private void add_to_local_edge_list(edge_store e) { //____________________________________________________________________________________________________________________________________________________________________ // !! Addition on main list here Form1.planar_object_store.edge2d temp_edge = new Form1.planar_object_store.edge2d(e.edge_id, e.start_pt.get_parent_data_type, e.end_pt.get_parent_data_type); local_output_edges.Add(temp_edge); }
public void delete_edge(edge_store edge_to_delete) { int edge_index = this._connected_edge_list.FindIndex(obj => obj.Equals(edge_to_delete)); if (edge_index != -1) { this._connected_edge_list.RemoveAt(edge_index); } }
private void remove_from_local_edge_list(edge_store e) { //____________________________________________________________________________________________________________________________________________________________________ // !! Addition on main list here Form1.planar_object_store.edge2d temp_edge = new Form1.planar_object_store.edge2d(e.edge_id, e.start_pt.get_parent_data_type, e.end_pt.get_parent_data_type); int temp_id = local_output_edges.FindLastIndex(obj => obj.edge_id == e.edge_id); local_output_edges.RemoveAt(temp_id); //local_output_edges.Remove(temp_edge); }
public void delaunay_divide_n_conquer(List <point_store> left_list, List <point_store> right_list) { // main divide and conquer recursive function // Left if (left_list.Count > 3) { int half_length = Convert.ToInt32(Math.Ceiling(left_list.Count / 2.0f)); List <point_store> left_left_list = left_list.GetRange(0, half_length); // extract the left list List <point_store> left_right_list = left_list.GetRange(half_length, left_list.Count - half_length); // extract the right list // delaunay divide and conquer delaunay_divide_n_conquer(left_left_list, left_right_list); } else { if (left_list.Count == 3) { add_triangle(left_list[0], left_list[1], left_list[2]); } else // pts.count == 2 { { add_edge(left_list[0], left_list[1]); } } } // Right if (right_list.Count > 3) { int half_length = Convert.ToInt32(Math.Ceiling(right_list.Count / 2.0f)); List <point_store> right_left_list = right_list.GetRange(0, half_length); // extract the left list List <point_store> right_right_list = right_list.GetRange(half_length, right_list.Count - half_length); // extract the right list // delaunay divide and conquer delaunay_divide_n_conquer(right_left_list, right_right_list); } else { if (right_list.Count == 3) { add_triangle(right_list[0], right_list[1], right_list[2]); } else // pts.count == 2 { { add_edge(right_list[0], right_list[1]); } } } edge_store baseLR = find_intial_baseLR(left_list, right_list); //Link LR edges Merge_LRedges(baseLR); }
public bool contains_edge(edge_store the_edge) { // find whether the edge belongs to the triangle if (the_edge.Equals_without_orientation(this._e1) == true || the_edge.Equals_without_orientation(this._e2) == true || the_edge.Equals_without_orientation(this._e3) == true) { return(true); } return(false); }
public bool equal_edge(edge_store other_e) { if (other_e.Equals(this.e1) == true || other_e.Equals(this.e2) == true || other_e.Equals(this.e3) == true) { return(true); } else { return(false); } }
private edge_store get_edge_away_from_this_pt(edge_store the_edge) { // This function returns the edge oriented from this point point_store this_pt = new point_store(this._pt_id, this._x, this._y, this.store_parent_data); if (the_edge.start_pt.Equals(this_pt) == false) { return(new edge_store(the_edge.edge_id, this_pt, the_edge.the_other_pt(this_pt))); } else { return(the_edge); } }
private void add_edge(point_store p1, point_store p2) { int edge_id = get_unique_edge_id(); edge_store e = new edge_store(edge_id, p1, p2); // Update the points p1 & p2 -> edge id lists // Note points are never removed from the list so indexing is easier (pt_id remains the same) pt_list[p1.pt_id].add_sorted_edge(e); pt_list[p2.pt_id].add_sorted_edge(e); edge_list.Add(e); // Add the edge e to the list add_to_local_list(e, null); }
private void delete_from_local_list(edge_store e, int t1_id, int t2_id) { Form1.planar_object_store.edge2d temp_edge, temp_edge_sym; int rem_index; // edge e // !! removal on main list here temp_edge = new Form1.planar_object_store.edge2d(e.edge_id, e.start_pt.get_parent_data_type, e.end_pt.get_parent_data_type); temp_edge_sym = new Form1.planar_object_store.edge2d(e.edge_id, e.end_pt.get_parent_data_type, e.start_pt.get_parent_data_type); rem_index = local_output_edges.FindIndex(obj => obj.Equals(temp_edge) || obj.Equals(temp_edge_sym)); if (rem_index != -1) { local_output_edges.RemoveAt(rem_index); // !! Deletion on main list here if (t1_id != -1 || t2_id != -1) // Check whether triangle need to be removed { if (t1_id < t2_id) // swap to remove in order { int temp = t1_id; t1_id = t2_id; t2_id = temp; } if (t1_id != -1) { int t1_index = local_output_triangle.FindIndex(obj => obj.face_id == triangle_list[t1_id].tri_id); local_output_triangle.RemoveAt(t1_index); } if (t2_id != -1) { int t2_index = local_output_triangle.FindIndex(obj => obj.face_id == triangle_list[t2_id].tri_id); local_output_triangle.RemoveAt(t2_index); } } // ################################################################# Form1.planar_object_store.instance_tracker temp_edge_tracker = new Form1.planar_object_store.instance_tracker(); temp_edge_tracker.edge_list = new List <Form1.planar_object_store.edge2d>(); temp_edge_tracker.edge_list.AddRange(local_output_edges); temp_edge_tracker.face_list = new List <Form1.planar_object_store.face2d>(); temp_edge_tracker.face_list.AddRange(local_output_triangle); local_history_tracker.Add(temp_edge_tracker); // ################################################################# } }
public edge_store cw_vertical_edge(edge_store with_edge) // clockwise vertical edge { int index_of_next = this._connected_edge_list.FindIndex(obj => obj.edge_id == with_edge.edge_id); if (index_of_next == -1) // object not found { return(null); // this should never happen } index_of_next--; // next clockwise edge in the list if (index_of_next == -1) // check if the index reached begining { index_of_next = this._connected_edge_list.Count - 1; //cycle back to end (reverse) } return(cc_vertical_edge(index_of_next)); //0,1,2,..... }
public edge_store cc_vertical_edge(edge_store with_edge) //counter clockwise vertical edge { int index_of_next = this._connected_edge_list.FindIndex(obj => obj.edge_id == with_edge.edge_id); if (index_of_next == -1) // object not found { return(null); // this should never happen } index_of_next++; // next counter clockwise edge in the list if (index_of_next == this._connected_edge_list.Count) // check if the index reached end { index_of_next = 0; //cycle back to zero } return(cc_vertical_edge(index_of_next)); //0,1,2,..... }
public triangle_store(int i_tri_id, point_store i_p1, point_store i_p2, point_store i_p3, edge_store i_e1, edge_store i_e2, edge_store i_e3) { // Constructor // set id this._tri_id = i_tri_id; // set points this._pt1 = i_p1; this._pt2 = i_p2; this._pt3 = i_p3; // set edges this._e1 = i_e1; this._e2 = i_e2; this._e3 = i_e3; // set the mid point this._mid_pt = new point_store(-1, (this._pt1.x + this._pt2.x + this._pt3.x) / 3.0f, (this._pt1.y + this._pt2.y + this._pt3.y) / 3.0f, null); }
public point_store get_other_pt(edge_store the_edge) { // Returns the third vertex of this triangle which is not part of the given edge if (the_edge.Equals_without_orientation(this.e1) == true) { return(this.e2.find_common_pt(this.e3)); } else if (the_edge.Equals_without_orientation(this.e2) == true) { return(this.e3.find_common_pt(this.e1)); } else if (the_edge.Equals_without_orientation(this.e3) == true) { return(this.e1.find_common_pt(this.e2)); } return(null); }
public void add_sorted_edge(edge_store edge_to_add) { // Add the edges as counter clock wise to the sorted list // this_pt // |\ // | \ // | \ // | \ // | \ // | \ // V V // vertical edge_0 //____________________________________________________________________________________ edge_to_add = get_edge_away_from_this_pt(edge_to_add); // Always add edge away from this point if (this._connected_edge_list.Count == 0) { this._connected_edge_list.Add(edge_to_add); return; } if (new edge_angle_comparer_vertical().Compare(this._connected_edge_list[this._connected_edge_list.Count - 1], edge_to_add) <= 0) // Equal to zero should not occur { this._connected_edge_list.Add(edge_to_add); return; } if (new edge_angle_comparer_vertical().Compare(this._connected_edge_list[0], edge_to_add) >= 0) // Equal to zero should not occur { this._connected_edge_list.Insert(0, edge_to_add); // Insert at zero because all the other angles are higher return; } // Uses a binary search algorithm to locate a specific element in the sorted List<edge_store> int index = this._connected_edge_list.BinarySearch(edge_to_add, new edge_angle_comparer_vertical()); if (index < 0) { index = ~index; // Bitwise Complement operator is represented by ~.It is a unary operator, i.e.operates on only one operand.The ~ operator inverts each bits i.e.changes 1 to 0 and 0 to 1. } this._connected_edge_list.Insert(index, edge_to_add); }
public point_store find_common_pt(edge_store other_edge) { // Returns the common point of this edge and the other edges if (this.start_pt.Equals(other_edge.start_pt)) { return(this.start_pt); } else if (this.start_pt.Equals(other_edge.end_pt)) { return(this.start_pt); } else if (this.end_pt.Equals(other_edge.start_pt)) { return(this.end_pt); } else if (this.end_pt.Equals(other_edge.end_pt)) { return(this.end_pt); } return(null); }
public bool commutative_equal(edge_store other) // commutative equals check edges with same two points but different orientation { return((this._start_pt.Equals(other.start_pt) && this._end_pt.Equals(other.end_pt)) || (this._end_pt.Equals(other.start_pt) && this._start_pt.Equals(other.end_pt))); }
public bool Equals(edge_store other) // orientation is important { return(this._start_pt.Equals(other.start_pt) && this._end_pt.Equals(other.end_pt)); }
private bool rightof(point_store x, edge_store e) { return(ccw(x, e.end_pt, e.start_pt)); }
public void Merge_LRedges(edge_store baseLRedge) { edge_store baseLRedge_sym = new edge_store(baseLRedge.edge_id, baseLRedge.end_pt, baseLRedge.start_pt); // symmetry of baseLRedge edge_store lcand = baseLRedge.start_pt.cc_vertical_edge(baseLRedge); // left candidate edge_store rcand = baseLRedge.end_pt.cw_vertical_edge(baseLRedge_sym); // rigth candidate // Left side Remove operation if (leftof(lcand.end_pt, baseLRedge) == true) // if the left candidate end point is not leftof baseLRedge then top is reached with baseLRedge and the end point of leftcandidate will not lie inCircle { edge_store lcand_next = baseLRedge.start_pt.cc_vertical_edge(lcand); // find the next candidate by counter clockwise cycle at baseLRedge start point with the current left candidate as qualifier while (incircle(baseLRedge.start_pt, baseLRedge.end_pt, lcand.end_pt, lcand_next.end_pt) == true) { edge_store new_lcand = baseLRedge.start_pt.cc_vertical_edge(lcand); // find the next candidate by counter clockwise cycle at baseLRedge start point with the current left candidate as qualifier remove_edge(lcand.edge_id); lcand = new_lcand; lcand_next = baseLRedge.start_pt.cc_vertical_edge(lcand); } } // Right side Remove operation if (rightof(rcand.end_pt, baseLRedge_sym) == true) // if the right candidate end point is not rightof baseLRedge_sym then top is reached with baseLRedge and the end point of rightcandidate will not lie inCircle { edge_store rcand_next = baseLRedge.end_pt.cw_vertical_edge(rcand); // find the next candidate by clockwise cycle at baseLRedge end point with the current right candidate as qualifier while (incircle(baseLRedge_sym.end_pt, baseLRedge_sym.start_pt, rcand.end_pt, rcand_next.end_pt) == true) { edge_store new_rcand = baseLRedge.end_pt.cw_vertical_edge(rcand); // find the next candidate by clockwise cycle at baseLRedge end point with the current right candidate as qualifier remove_edge(rcand.edge_id); rcand = new_rcand; rcand_next = baseLRedge.end_pt.cw_vertical_edge(rcand); } } bool lvalid, rvalid; lvalid = leftof(lcand.end_pt, baseLRedge); // validity of left candidate rvalid = rightof(rcand.end_pt, baseLRedge_sym); // validity of right candidate // The next cross edge is to be connected to either lcand.end_pt or rcand.end_pt if (lvalid == true && rvalid == true) // both are valid, then choose the correct end with in-circle test { if (incircle(baseLRedge.start_pt, baseLRedge.end_pt, lcand.end_pt, rcand.end_pt) == true) //right candidate end point lies inside in circle formed by left candidate { add_edge_with_triangle(baseLRedge.start_pt, rcand.end_pt); // so form the edge with right candidate end point } else // left candidate end point in cicle doesn't enclose right candidate end point { add_edge_with_triangle(lcand.end_pt, baseLRedge_sym.start_pt); // so form the edge with left candidate end point } } else if (lvalid == true) { add_edge_with_triangle(lcand.end_pt, baseLRedge_sym.start_pt);// Add cross edge base1 from lcand.end_pt to baseLRedge_sym.start_pt } else if (rvalid == true) { add_edge_with_triangle(baseLRedge.start_pt, rcand.end_pt);// Add cross edge basel frombaseLRedge.start_pt to rcand.end_pt } else { // both lcand and rcand are making obtuse angle with baseLRedge, then baseLRedge is the upper common tangent return; // end of recursion } edge_store new_baseLRedge = edge_list[edge_list.Count - 1]; // new baseLRedge is the last created edge Merge_LRedges(new_baseLRedge); // Recursion here }
private static bool leftof(point_store x, edge_store e) { return(ccw(x, e.start_pt, e.end_pt)); }
private void add_edge_with_triangle(point_store p1, point_store p2) { int edge_id = get_unique_edge_id(); edge_store e = new edge_store(edge_id, p1, p2); // Update the points p1 & p2 -> edge id lists // Note points are never removed from the list so indexing is easier (pt_id remains the same) pt_list[p1.pt_id].add_sorted_edge(e); pt_list[p2.pt_id].add_sorted_edge(e); // Now find the other two edges connected to this edge forming a triangle bool is_triangle_found = false; edge_store second_edge, third_edge; // clockwise search second_edge = e.end_pt.cc_vertical_edge(e); third_edge = second_edge.end_pt.cc_vertical_edge(second_edge); if (third_edge.end_pt.Equals(e.start_pt) == true) { is_triangle_found = true; } else { // counter clockwise search second_edge = e.end_pt.cw_vertical_edge(e); third_edge = second_edge.end_pt.cw_vertical_edge(second_edge); if (third_edge.end_pt.Equals(e.start_pt) == true) { is_triangle_found = true; } } edge_list.Add(e); // Add the edge e to the list if (is_triangle_found == true) // must found otherwise something went wrong { int tri_id = get_unique_triangle_id(); int second_edge_index, third_edge_index; second_edge_index = edge_list.FindIndex(obj => obj.edge_id == second_edge.edge_id); third_edge_index = edge_list.FindIndex(obj => obj.edge_id == third_edge.edge_id); edge_list[second_edge_index].add_triangle_id(tri_id); // got lazy.. need to develop more efficient method edge_list[third_edge_index].add_triangle_id(tri_id); // got lazy.. need to develop more efficient method // Update the edge triangle id edge_list[edge_list.Count - 1].add_triangle_id(tri_id); //Add the triangle triangle_list.Add(new triangle_store(tri_id, e.start_pt, e.end_pt, second_edge.the_other_pt(e.end_pt))); triangle_list[triangle_list.Count - 1].e1 = edge_list[third_edge_index]; triangle_list[triangle_list.Count - 1].e2 = edge_list[second_edge_index]; triangle_list[triangle_list.Count - 1].e3 = edge_list[edge_list.Count - 1]; } add_to_local_list(e, is_triangle_found == true ? triangle_list[triangle_list.Count - 1] : null); }