public point_store add(point_store other_pt) { double ab_x = this.x + other_pt.x; double ab_y = this.y + other_pt.y; return(new point_store(-1, ab_x, ab_y, null)); }
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 set_bounding_triangle(List <point_store> all_input_vertices) { point_store[] x_sorted = all_input_vertices.OrderBy(obj => obj.x).ToArray(); point_store[] y_sorted = all_input_vertices.OrderBy(obj => obj.y).ToArray(); // Define bounding triangle double max_x, max_y, k; max_x = (x_sorted[x_sorted.Length - 1].x - x_sorted[0].x); max_y = (y_sorted[y_sorted.Length - 1].y - y_sorted[0].y); k = 1000 * Math.Max(max_x, max_y); // zeoth _point double x_zero, y_zero; x_zero = (x_sorted[x_sorted.Length - 1].x + x_sorted[0].x) * 0.5; y_zero = (y_sorted[y_sorted.Length - 1].y + y_sorted[0].y) * 0.5; // id for the super triangle points int pt_count = all_input_vertices.Count; // set the vertex this.s_p1 = new point_store(pt_count + 1, 0, Math.Round(k / 2.0f), new Form1.planar_object_store.point2d(pt_count + 1, x_zero, k)); this.s_p2 = new point_store(pt_count + 2, Math.Round(k / 2.0f), 0.0, new Form1.planar_object_store.point2d(pt_count + 2, k, y_zero)); this.s_p3 = new point_store(pt_count + 3, -1 * Math.Round(k / 2.0f), -1 * Math.Round(k / 2.0f), new Form1.planar_object_store.point2d(pt_count + 3, -k, -k)); local_input_points.Add(new Form1.planar_object_store.point2d(this.s_p1.pt_id, this.s_p1.x, this.s_p1.y)); local_input_points.Add(new Form1.planar_object_store.point2d(this.s_p2.pt_id, this.s_p2.x, this.s_p2.y)); local_input_points.Add(new Form1.planar_object_store.point2d(this.s_p3.pt_id, this.s_p3.x, this.s_p3.y)); // set the edges add_triangle(this.s_p1, this.s_p2, this.s_p3); }
public bool Equals(point_store other) { if (Math.Abs(this._x - other.x) <= eps && Math.Abs(this._y - other.y) <= eps) { return(true); } return(false); }
public edge_store(int i_e_id, point_store s, point_store e) { this._edge_id = i_e_id; // id of the edge this._start_pt = s; this._end_pt = e; this.tri1_id = -1; this.tri2_id = -1; }
public bool contains_point(point_store the_point) { // find whether the point belongs to the triangle if (the_point.Equals(this._start_pt) == true || the_point.Equals(this._end_pt) == true) { return(true); } return(false); }
private int add_triangle(point_store p1, point_store p2, point_store p3) { int edge_index1 = -1; int edge_index2 = -1; int edge_index3 = -1; // Edge 1 edge_index1 = this.all_edges.FindLastIndex(obj => obj.Equals_without_orientation(new edge_store(-1, p1, p2))); if (edge_index1 == -1) { edge_index1 = this.all_edges.Count; this._all_edges.Add(new edge_store(get_unique_edge_id(), p1, p2)); // Add to the output variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! add_to_local_edge_list(this.all_edges[this.all_edges.Count - 1]); } // Edge 2 edge_index2 = this.all_edges.FindLastIndex(obj => obj.Equals_without_orientation(new edge_store(-1, p2, p3))); if (edge_index2 == -1) { edge_index2 = this.all_edges.Count; this._all_edges.Add(new edge_store(get_unique_edge_id(), p2, p3)); // Add to the output variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! add_to_local_edge_list(this.all_edges[this.all_edges.Count - 1]); } // Edge 3 edge_index3 = this.all_edges.FindLastIndex(obj => obj.Equals_without_orientation(new edge_store(-1, p3, p1))); if (edge_index3 == -1) { edge_index3 = this.all_edges.Count; this._all_edges.Add(new edge_store(get_unique_edge_id(), p3, p1)); // Add to the output variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! add_to_local_edge_list(this.all_edges[this.all_edges.Count - 1]); } // Triangle this._all_triangles.Add(new triangle_store(get_unique_triangle_id(), p1, p2, p3, this.all_edges[edge_index1], this.all_edges[edge_index2], this.all_edges[edge_index3])); // Update the triangle details to the edge this._all_edges[edge_index1].add_triangle(this.all_triangles[this.all_triangles.Count - 1]); this._all_edges[edge_index2].add_triangle(this.all_triangles[this.all_triangles.Count - 1]); this._all_edges[edge_index3].add_triangle(this.all_triangles[this.all_triangles.Count - 1]); // Add to the output variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! add_to_local_trianlge_list(this.all_triangles[this.all_triangles.Count - 1]); return(this.all_triangles[this.all_triangles.Count - 1].tri_id); }
private void add_triangle(point_store p1, point_store p2, point_store p3) { // Add the first two edge add_edge(p1, p2); add_edge(p2, p3); // Check colinearity of p1, p2, p3 if (is_collinear(p1, p2, p3) == false) // Add the third edge only when collinear is false { add_edge_with_triangle(p3, p1); // Add third edge with triangle } }
public point_store find_other_pt(point_store pt) { if (this.start_pt.Equals(pt) == true) { return(this.end_pt); } else if (this.end_pt.Equals(pt) == true) { return(this.start_pt); } return(null); }
public edge_store(int i_edge_id, point_store i_start_pt, point_store i_end_pt) { // Constructor // set id this._edge_id = i_edge_id; // set start and end pt this._start_pt = i_start_pt; this._end_pt = i_end_pt; // set triangles to null this._left_triangle = null; this._right_triangle = null; }
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 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); } }
public bool is_point_inside(point_store the_pt) { double d1, d2, d3; bool has_neg, has_pos; d1 = calc_det(the_pt, this._pt1, this._pt2); d2 = calc_det(the_pt, this._pt2, this._pt3); d3 = calc_det(the_pt, this._pt3, this._pt1); has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0); has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0); return(!(has_neg && has_pos)); }
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); }
private void flip_bad_edges(int tri_id, point_store pt) { // find the triangle with input id int tri_index = this.all_triangles.FindLastIndex(obj => obj.tri_id == tri_id); // find the edge of this triangle whihc does not contain pt int common_edge_index = this.all_edges.FindLastIndex(obj => obj.edge_id == this.all_triangles[tri_index].get_other_edge_id(pt)); // main method to legalize edges by recursively flipping all the illegal edges int neighbour_tri_index = this.all_triangles.FindIndex(obj => obj.tri_id == this.all_edges[common_edge_index].other_triangle_id(this.all_triangles[tri_index])); // legalize only if the triangle has a neighbour if (neighbour_tri_index != -1) { // check whether the newly added pt is inside the neighbour triangle if (this.all_triangles[neighbour_tri_index].is_point_in_circumcircle(pt) == true) { // find the other vertex of the closest triangle point_store neighbour_tri_other_vertex = this.all_triangles[neighbour_tri_index].get_other_pt(this.all_edges[common_edge_index]); point_store edge_a_pt = this.all_edges[common_edge_index].start_pt; point_store edge_b_pt = this.all_edges[common_edge_index].end_pt; // Remove the common edge // remove_edge(the_edge); // int edge_index = this._all_edges.FindLastIndex(obj => obj.edge_id == the_edge.edge_id); unique_edgeid_list.Add(this.all_edges[common_edge_index].edge_id); // Remove from the output variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! remove_from_local_edge_list(this.all_edges[common_edge_index]); this._all_edges.RemoveAt(common_edge_index); // Remove the two triangles remove_triangle(tri_index); remove_triangle(neighbour_tri_index); // Add two triangles int first_triangle_id, second_triangle_id; first_triangle_id = add_triangle(pt, neighbour_tri_other_vertex, edge_a_pt); second_triangle_id = add_triangle(pt, neighbour_tri_other_vertex, edge_b_pt); // recursion below flip_bad_edges(first_triangle_id, pt); flip_bad_edges(second_triangle_id, pt); } } }
public int get_other_edge_id(point_store pt) { if (this.e1.start_pt.Equals(pt) == false && this.e1.end_pt.Equals(pt) == false) { return(this.e1.edge_id); } else if (this.e2.start_pt.Equals(pt) == false && this.e2.end_pt.Equals(pt) == false) { return(this.e2.edge_id); } else if (this.e3.start_pt.Equals(pt) == false && this.e3.end_pt.Equals(pt) == false) { return(this.e3.edge_id); } return(-1); }
// Tests if a given point lies in the circumcircle of this triangle.Let the // triangle ABC appear in counterclockwise (CCW) order. Then when det > // 0, the point lies inside the circumcircle through the three points a, b // and c.If instead det < 0, the point lies outside the circumcircle. // When det = 0, the four points are cocircular.If the triangle is oriented // clockwise (CW) the result is reversed.See Real-Time Collision Detection, // chap. 3, p. 34. public bool is_point_in_circumcircle(point_store the_pt) { double a11 = pt1.x - the_pt.x; double a21 = pt2.x - the_pt.x; double a31 = pt3.x - the_pt.x; double a12 = pt1.y - the_pt.y; double a22 = pt2.y - the_pt.y; double a32 = pt3.y - the_pt.y; double a13 = (pt1.x - the_pt.x) * (pt1.x - the_pt.x) + (pt1.y - the_pt.y) * (pt1.y - the_pt.y); double a23 = (pt2.x - the_pt.x) * (pt2.x - the_pt.x) + (pt2.y - the_pt.y) * (pt2.y - the_pt.y); double a33 = (pt3.x - the_pt.x) * (pt3.x - the_pt.x) + (pt3.y - the_pt.y) * (pt3.y - the_pt.y); double det = (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 - a13 * a22 * a31 - a12 * a21 * a33 - a11 * a23 * a32); return((is_oriented_ccw() == true) ? det > 0.0 : det < 0.0); }
public double find_closest_distance(point_store pt) { point_store ab = end_pt.sub(start_pt); // ab_x = x2 - x1, ab_y = y2 - y1 (end_pt - start_pt) double ab_dot = ab.dot(ab); // ab_x*ab_x + ab_y*ab_y // double u=((x3 - x1) * px + (y3 - y1) * py) / ((px*px)+(py*py)); double u = (pt.sub(start_pt)).dot(ab) / ab_dot; if (u < 0.0) { u = 0.0; } else if (u > 1.0) { u = 1.0; } // closest point on the edge from the input pt point_store c = start_pt.add(ab.mult(u)); // vector connecting the input pt and the pt on line point_store pt_to_c = c.sub(pt); return(pt_to_c.dot(pt_to_c)); }
public mesh_store(List <point_store> input_vertices, ref List <Form1.planar_object_store.point2d> parent_inpt_points) { local_input_points = parent_inpt_points; // intialize the edges and triangles this._all_edges = new List <edge_store>(); this._all_triangles = new List <triangle_store>(); // Create an imaginary triangle that encloses all the point set set_bounding_triangle(input_vertices); foreach (point_store pt in input_vertices) { // Find the index of triangle containing this point int containing_triangle_index = this.all_triangles.FindIndex(obj => obj.is_point_inside(pt) == true); point_store tri_a = this.all_triangles[containing_triangle_index].pt1; point_store tri_b = this.all_triangles[containing_triangle_index].pt2; point_store tri_c = this.all_triangles[containing_triangle_index].pt3; remove_triangle(containing_triangle_index); // add the triangle int first_triangle_id, second_triangle_id, third_triangle_id; first_triangle_id = add_triangle(pt, tri_a, tri_b); second_triangle_id = add_triangle(pt, tri_b, tri_c); third_triangle_id = add_triangle(pt, tri_c, tri_a); // Flip the bad triangles recursively flip_bad_edges(first_triangle_id, pt); flip_bad_edges(second_triangle_id, pt); flip_bad_edges(third_triangle_id, pt); } // Revise output edges and triangles local_output_edges = new List <Form1.planar_object_store.edge2d>(); local_output_triangle = new List <Form1.planar_object_store.face2d>(); List <edge_store> revised_edges = new List <edge_store>(); revised_edges = this.all_edges.FindAll(obj => obj.contains_point(this.s_p1) == false && obj.contains_point(this.s_p2) == false && obj.contains_point(this.s_p3) == false).ToList(); int i = 0; foreach (edge_store the_edge in revised_edges) { local_output_edges.Add(new Form1.planar_object_store.edge2d(i, the_edge.start_pt.get_parent_data_type, the_edge.end_pt.get_parent_data_type)); i++; } List <triangle_store> revised_tris = new List <triangle_store>(); revised_tris = this.all_triangles.FindAll(obj => obj.contains_point(this.s_p1) == false && obj.contains_point(this.s_p2) == false && obj.contains_point(this.s_p3) == false).ToList(); i = 0; foreach (triangle_store the_edge in revised_tris) { local_output_triangle.Add(new Form1.planar_object_store.face2d(i, the_edge.pt1.get_parent_data_type, the_edge.pt2.get_parent_data_type, the_edge.pt3.get_parent_data_type)); i++; } }
public bool Equals(point_store other) { return(this.x == other.x && this.y == other.y); }
public double dot(point_store other_pt) { return((this.x * other_pt.x) + (this.y * other_pt.y)); }
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); }
private bool rightof(point_store x, edge_store e) { return(ccw(x, e.end_pt, e.start_pt)); }
// Find the area of a triangle.This function uses the 1/2 determinant // method. Given three points (x1, y1), (x2, y2), (x3, y3): // | x1 y1 1 | // Area = 0.5 * | x2 y2 1 | // | x3 y3 1 | public double calc_det(point_store p1, point_store p2, point_store p3) { return((p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y)); }