public void PlaneConstructionTest() { var p1 = new Coordinate(-100, -100, 100); var p2 = new Coordinate(100, -100, 100); var p3 = new Coordinate(100, 100, 100); var p4 = new Coordinate(0, 0, 0); var refPlane = new Plane(new Coordinate(0, 0, 1), 100); var plane = new Plane(p3, p2, p1); var o1 = refPlane.OnPlane(p1); var o2 = plane.OnPlane(p1); var o3 = refPlane.OnPlane(p4); var o4 = plane.OnPlane(p4); Assert.IsTrue(o1 == 0); Assert.IsTrue(o2 == 0); Assert.IsFalse(o3 == 0); Assert.IsFalse(o4 == 0); Assert.AreEqual(refPlane.A, plane.A); Assert.AreEqual(refPlane.B, plane.B); Assert.AreEqual(refPlane.C, plane.C); Assert.AreEqual(refPlane.D, plane.D); var plane2 = new Plane(new Coordinate(-192, 704, 192), new Coordinate(-192, 320, 192), new Coordinate(-192, 320, -192)); }
/// <summary> /// Determines if this line is behind, in front, or spanning a plane. /// </summary> /// <param name="p">The plane to test against</param> /// <returns>A PlaneClassification value.</returns> public PlaneClassification ClassifyAgainstPlane(Plane p) { var start = p.OnPlane(Start); var end = p.OnPlane(End); if (start == 0 && end == 0) return PlaneClassification.OnPlane; if (start <= 0 && end <= 0) return PlaneClassification.Back; if (start >= 0 && end >= 0) return PlaneClassification.Front; return PlaneClassification.Spanning; }
/// <summary> /// Determines if this polygon is behind, in front, or spanning a plane. /// </summary> /// <param name="p">The plane to test against</param> /// <returns>A PlaneClassification value.</returns> public PlaneClassification ClassifyAgainstPlane(Plane p) { int front = 0, back = 0, onplane = 0, count = Vertices.Count; foreach (var test in Vertices.Select(x => p.OnPlane(x))) { // Vertices on the plane are both in front and behind the plane in this context if (test <= 0) { back++; } if (test >= 0) { front++; } if (test == 0) { onplane++; } } if (onplane == count) { return(PlaneClassification.OnPlane); } if (front == count) { return(PlaneClassification.Front); } if (back == count) { return(PlaneClassification.Back); } return(PlaneClassification.Spanning); }
private void RenderLine(Vector3 start, Vector3 end, Plane plane, Color color, ICamera camera, Graphics graphics) { var line = new Line(start, end); var cls = line.ClassifyAgainstPlane(plane); if (cls == PlaneClassification.Back) { return; } if (cls == PlaneClassification.Spanning) { var isect = plane.GetIntersectionPoint(line, true); var first = plane.OnPlane(line.Start) > 0 ? line.Start : line.End; if (!isect.HasValue) { return; } line = new Line(first, isect.Value); } var st = camera.WorldToScreen(line.Start); var en = camera.WorldToScreen(line.End); using (var p = new Pen(color, 2)) { graphics.DrawLine(p, st.X, st.Y, en.X, en.Y); } }
private void RenderLine(Vector3 start, Vector3 end, Plane plane, Color color, ICamera camera, I2DRenderer im) { var line = new Line(start, end); var cls = line.ClassifyAgainstPlane(plane); if (cls == PlaneClassification.Back) { return; } if (cls == PlaneClassification.Spanning) { var isect = plane.GetIntersectionPoint(line, true); var first = plane.OnPlane(line.Start) > 0 ? line.Start : line.End; if (!isect.HasValue) { return; } line = new Line(first, isect.Value); } var st = camera.WorldToScreen(line.Start); var en = camera.WorldToScreen(line.End); im.AddLine(st.ToVector2(), en.ToVector2(), color, 2); }
/// <summary> /// Determines if this line is behind, in front, or spanning a plane. /// </summary> /// <param name="p">The plane to test against</param> /// <returns>A PlaneClassification value.</returns> public PlaneClassification ClassifyAgainstPlane(Plane p) { var start = p.OnPlane(Start); var end = p.OnPlane(End); if (start == 0 && end == 0) { return(PlaneClassification.OnPlane); } if (start <= 0 && end <= 0) { return(PlaneClassification.Back); } if (start >= 0 && end >= 0) { return(PlaneClassification.Front); } return(PlaneClassification.Spanning); }
/// <summary> /// Determines if this polygon is behind, in front, or spanning a plane. /// </summary> /// <param name="p">The plane to test against</param> /// <returns>A PlaneClassification value.</returns> public PlaneClassification ClassifyAgainstPlane(Plane p) { int front = 0, back = 0, onplane = 0, count = Vertices.Count; foreach (var test in Vertices.Select(x => p.OnPlane(x))) { // Vertices on the plane are both in front and behind the plane in this context if (test <= 0) back++; if (test >= 0) front++; if (test == 0) onplane++; } if (onplane == count) return PlaneClassification.OnPlane; if (front == count) return PlaneClassification.Front; if (back == count) return PlaneClassification.Back; return PlaneClassification.Spanning; }
private void AddLine(CircleType type, Vector3 start, Vector3 end, Plane test, CachedLines cache) { var line = new Line(start, end); var cls = line.ClassifyAgainstPlane(test); if (cls == PlaneClassification.Back) { return; } if (cls == PlaneClassification.Spanning) { var isect = test.GetIntersectionPoint(line, true); var first = test.OnPlane(line.Start) > 0 ? line.Start : line.End; if (isect.HasValue) { line = new Line(first, isect.Value); } } cache.Cache[type].Add(new Line(cache.Viewport.Camera.WorldToScreen(line.Start), cache.Viewport.Camera.WorldToScreen(line.End))); }
/// <summary> /// Determines if this polygon is behind, in front, or spanning a plane. /// </summary> /// <param name="p">The plane to test against</param> /// <returns>A PlaneClassification value.</returns> public PlaneClassification ClassifyAgainstPlane(Plane p) { var count = Vertices.Count; var front = 0; var back = 0; var onplane = 0; foreach (var t in Vertices) { var test = p.OnPlane(t); // Vertices on the plane are both in front and behind the plane in this context if (test <= 0) { back++; } if (test >= 0) { front++; } if (test == 0) { onplane++; } } if (onplane == count) { return(PlaneClassification.OnPlane); } if (front == count) { return(PlaneClassification.Front); } if (back == count) { return(PlaneClassification.Back); } return(PlaneClassification.Spanning); }
/// <summary> /// Splits this polygon by a clipping plane, returning the back and front planes. /// The original polygon is not modified. /// </summary> /// <param name="clip">The clipping plane</param> /// <param name="back">The back polygon</param> /// <param name="front">The front polygon</param> /// <returns>True if the split was successful</returns> public bool Split(Plane clip, out Polygon back, out Polygon front) { // If the polygon doesn't span the plane, return false. var classify = ClassifyAgainstPlane(clip); if (classify != PlaneClassification.Spanning) { back = front = null; if (classify == PlaneClassification.Back) back = this; else if (classify == PlaneClassification.Front) front = this; return false; } // Get the new front and back vertices var backVerts = new List<Coordinate>(); var frontVerts = new List<Coordinate>(); var prev = 0; for (var i = 0; i <= Vertices.Count; i++) { var end = Vertices[i % Vertices.Count]; var cls = clip.OnPlane(end); // Check plane crossing if (i > 0 && cls != 0 && prev != 0 && prev != cls) { // This line end point has crossed the plane // Add the line intersect to the var start = Vertices[i - 1]; var line = new Line(start, end); var isect = clip.GetIntersectionPoint(line, true); if (isect == null) throw new Exception("Expected intersection, got null."); frontVerts.Add(isect); backVerts.Add(isect); } // Add original points if (i < Vertices.Count) { // OnPlane points get put in both polygons, doesn't generate split if (cls >= 0) frontVerts.Add(end); if (cls <= 0) backVerts.Add(end); } prev = cls; } back = new Polygon(backVerts); front = new Polygon(frontVerts); return true; }
private void AddLine(CircleType type, Coordinate start, Coordinate end, Plane test, CachedLines cache) { var line = new Line(start, end); var cls = line.ClassifyAgainstPlane(test); if (cls == PlaneClassification.Back) return; if (cls == PlaneClassification.Spanning) { var isect = test.GetIntersectionPoint(line, true); var first = test.OnPlane(line.Start) > 0 ? line.Start : line.End; line = new Line(first, isect); } cache.Cache[type].Add(new Line(cache.Viewport3D.WorldToScreen(line.Start), cache.Viewport3D.WorldToScreen(line.End))); }
/// <summary> /// Splits this polygon by a clipping plane, returning the back and front planes. /// The original polygon is not modified. /// </summary> /// <param name="clip">The clipping plane</param> /// <param name="back">The back polygon</param> /// <param name="front">The front polygon</param> /// <param name="coplanarBack">If the polygon rests on the plane and points backward, this will not be null</param> /// <param name="coplanarFront">If the polygon rests on the plane and points forward, this will not be null</param> /// <returns>True if the split was successful</returns> public bool Split(Plane clip, out Polygon back, out Polygon front, out Polygon coplanarBack, out Polygon coplanarFront) { // If the polygon doesn't span the plane, return false. var classify = ClassifyAgainstPlane(clip); if (classify != PlaneClassification.Spanning) { back = front = null; coplanarBack = coplanarFront = null; if (classify == PlaneClassification.Back) { back = this; } else if (classify == PlaneClassification.Front) { front = this; } else if (Plane.Normal.Dot(clip.Normal) > 0) { coplanarFront = this; } else { coplanarBack = this; } return(false); } // Get the new front and back vertices var backVerts = new List <Coordinate>(); var frontVerts = new List <Coordinate>(); var prev = 0; for (var i = 0; i <= Vertices.Count; i++) { var end = Vertices[i % Vertices.Count]; var cls = clip.OnPlane(end); // Check plane crossing if (i > 0 && cls != 0 && prev != 0 && prev != cls) { // This line end point has crossed the plane // Add the line intersect to the var start = Vertices[i - 1]; var line = new Line(start, end); var isect = clip.GetIntersectionPoint(line, true); if (isect == null) { throw new Exception("Expected intersection, got null."); } frontVerts.Add(isect); backVerts.Add(isect); } // Add original points if (i < Vertices.Count) { // OnPlane points get put in both polygons, doesn't generate split if (cls >= 0) { frontVerts.Add(end); } if (cls <= 0) { backVerts.Add(end); } } prev = cls; } back = new Polygon(backVerts); front = new Polygon(frontVerts); coplanarBack = coplanarFront = null; return(true); }