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); }
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> /// 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; }
protected static Coordinate GetIntersectionPoint(IList<Coordinate> coordinates, Line line, bool ignoreDirection = false) { var plane = new Plane(coordinates[0], coordinates[1], coordinates[2]); var intersect = plane.GetIntersectionPoint(line, ignoreDirection); if (intersect == null) return null; // http://paulbourke.net/geometry/insidepoly/ // The angle sum will be 2 * PI if the point is inside the face double sum = 0; for (var i = 0; i < coordinates.Count; i++) { var i1 = i; var i2 = (i + 1) % coordinates.Count; // Translate the vertices so that the intersect point is on the origin var v1 = coordinates[i1] - intersect; var v2 = coordinates[i2] - intersect; var m1 = v1.VectorMagnitude(); var m2 = v2.VectorMagnitude(); var nom = m1 * m2; if (nom < 0.001m) { // intersection is at a vertex return intersect; } sum += Math.Acos((double)(v1.Dot(v2) / nom)); } var delta = Math.Abs(sum - Math.PI * 2); return (delta < 0.001d) ? intersect : null; }
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); }
public void PlaneLineIntersectionTest() { var plane = new Plane(new Coordinate(0, 0, 1), 100); var passLine = new Line(new Coordinate(0, 0, 0), new Coordinate(0, 0, 200)); var reversePassLine = passLine.Reverse(); var failSegment = new Line(new Coordinate(0, 0, 0), new Coordinate(0, 0, 50)); var failLine = new Line(new Coordinate(0, 0, 0), new Coordinate(1, 0, 0)); var pass1 = plane.GetIntersectionPoint(passLine); var pass2 = plane.GetIntersectionPoint(reversePassLine, true); var pass3 = plane.GetIntersectionPoint(failSegment, false, true); var fail1 = plane.GetIntersectionPoint(reversePassLine); var fail2 = plane.GetIntersectionPoint(failSegment); var fail3 = plane.GetIntersectionPoint(failLine); Assert.IsNotNull(pass1); Assert.IsNotNull(pass2); Assert.IsNotNull(pass3); Assert.IsNull(fail1); Assert.IsNull(fail2); Assert.IsNull(fail3); }