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 &gt;
                // 0, the point lies inside the circumcircle through the three points a, b
                // and c.If instead det &lt; 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));
 }