/// <summary> /// This function calculates the intersection point between a plane and a line. Replace the x,y,z components of the line equation into the plane equation and solve for t, then replace t in the line equation to get the x,y,z /// </summary> /// <param name="line"></param> /// <param name="plane"></param> /// <returns></returns> public static Point IntersectionLinePlane(Line line, Plane plane) { // could write in one line but it'd be too hard to debug, or read! // replace the x,y,z components of the line equation into the plane equation and solve for t double numerator = -plane.d - plane.a * line.P0.x - plane.b * line.P0.y - plane.c * line.P0.z; double denominator = plane.a * line.v.x + plane.b * line.v.y + plane.c * line.v.z; double t = numerator / denominator; // replace t in the line equation to get the x,y,z double x = t * line.v.x + line.P0.x; double y = t * line.v.y + line.P0.y; double z = t * line.v.z + line.P0.z; return new Point(x, y, z); }
private void buttonTest_Click(object sender, EventArgs e) { // test the function // setup test with one triangle and one plane // input a set of triangles List<Triangle> triangles = new List<Triangle>(); triangles.Add(new Triangle(new Point(-5, 10, 0), new Point(10, 10, 0), new Point(5, -10, 0))); triangles.Add(new Triangle(new Point(-5, 10, 5), new Point(10, 10, 5), new Point(5, -10, 5))); triangles.Add(new Triangle(new Point(-3, 10, 4), new Point(1, 10, -3), new Point(10, -13, 8))); triangles.Add(new Triangle(new Point(-5, 100, 0), new Point(10, 100, 0), new Point(5, 100, 0))); triangles.Add(new Triangle(new Point(-50, 13, 2), new Point(0, -4, 0), new Point(2, -10, 0))); // define the plane Plane plane = new Plane(-0.5, 1, 0.5, 0); // slice using a plane defined by normal equation, the plane does not have bounds List<Segment> segments = new List<Segment>(); foreach (Triangle triangle in triangles) { try { Segment segment = Triangle.TriangleInPlane(triangle, plane); if (segment != null) { segments.Add(segment); } } catch (Exception ex) { textBoxDebug.Text = ex.ToString(); } } // segments contain polylines from slicing a set of triangles textBoxDebug.Text = "done"; }
/// <summary> /// this function calculates th distance between a point and a plane. Using the normal equation, we plug the coordinates of the point and get the distance /// </summary> /// <param name="point"></param> /// <param name="plane"></param> /// <returns></returns> public double DistancePointPlane(Point point, Plane plane) { // the equation is distance = (a*x0 + b*y0 + c*z0 + d)/sqrt(a*a + b*b + c*c) // split the equation in two for ease of reading double numerator = (plane.a * point.x + plane.b * point.y + plane.c * point.z + plane.d); double denominator = Math.Sqrt(plane.a * plane.a + plane.b * plane.b + plane.c * plane.c); return numerator / denominator; }
/// <summary> /// this function finds the intersection between the triangle and the plane /// --> checks if the triangle intersects the plane /// --> if it intersects, it will look like a segment /// --> the ends of the segment are the intersections of the two edges of the triangle going through the plane and the plane /// </summary> /// <param name="triangle">the input triangle</param> /// <param name="plane">the input plane</param> /// <returns>segment if there is intersection, else return null</returns> public static Segment TriangleInPlane(Triangle triangle, Plane plane) { // // find side +/- of each of 3 points of triangle bool SidePoint1 = SidePointPlane(triangle.point1, plane); bool SidePoint2 = SidePointPlane(triangle.point2, plane); bool SidePoint3 = SidePointPlane(triangle.point3, plane); Point p1, p2; // point1 is lonely if (SidePoint1 != SidePoint2 && SidePoint2 == SidePoint3) { // get lines made by Point1-2 and Point1-3 Line l12 = new Line(triangle.point1, triangle.point2); Line l13 = new Line(triangle.point1, triangle.point3); // get intersection of lines and plane p1 = Line.IntersectionLinePlane(l12,plane); p2 = Line.IntersectionLinePlane(l13, plane); // return the segment made of those two points return new Segment(p1,p2); } else if (SidePoint2 != SidePoint1 && SidePoint1 == SidePoint3)// point2 is lonely { // get lines made by Point1-2 and Point1-3 Line l21 = new Line(triangle.point2, triangle.point1); Line l23 = new Line(triangle.point2, triangle.point3); // get intersection of lines and plane p1 = Line.IntersectionLinePlane(l21, plane); p2 = Line.IntersectionLinePlane(l23, plane); // return the segment made of those two points return new Segment(p1, p2); } else if (SidePoint3 != SidePoint2 && SidePoint1 == SidePoint2)// point3 is lonely { // get lines made by Point1-2 and Point1-3 Line l31 = new Line(triangle.point3, triangle.point1); Line l32 = new Line(triangle.point3, triangle.point2); // get intersection of lines and plane p1 = Line.IntersectionLinePlane(l31, plane); p2 = Line.IntersectionLinePlane(l32, plane); // return the segment made of those two points return new Segment(p1, p2); } else {// both points are on same side of plane, meaning that the triangle is not intersecting the plane return null; } }
/// <summary> /// this is the same as the distance but we only want the sign so we skip the division part which is time consuming /// </summary> /// <param name="point"></param> /// <param name="plane"></param> /// <returns></returns> public static bool SidePointPlane(Point point, Plane plane) { // side is a bit arbitrary because it depends on definition of the plane's normal vector // the equation is distance = (a*x0 + b*y0 + c*z0 + d)/sqrt(a*a + b*b + c*c) // since we only want the sign, we can ignore the division part // sign(a*x0 + b*y0 + c*z0 + d) return (plane.a * point.x + plane.b * point.y + plane.c * point.z + plane.d) >= 0; // return true if positive, false if negative }