/// <summary> /// Unproject a point from the screen (2D) to a point on plane (3D) /// </summary> /// <param name="p"> /// The 2D point. /// </param> /// <param name="position"> /// plane position /// </param> /// <param name="normal"> /// plane normal /// </param> /// <returns> /// A 3D point. /// </returns> public Point3D?UnProject(Point p, Point3D position, Vector3D normal) { Ray3D ray = this.GetRay(p); if (ray == null) { return(null); } return(ray.PlaneIntersection(position, normal)); }
/// <summary> /// Un projects a point from the screen (2D) to a point on plane (3D) /// </summary> /// <param name="p"> /// The 2D point. /// </param> /// <param name="position"> /// A point on the plane . /// </param> /// <param name="normal"> /// The plane normal. /// </param> /// <returns> /// A 3D point. /// </returns> public Point3D? UnProject(Point p, Point3D position, Vector3D normal) { Ray3D ray = this.GetRay(p); if (ray == null) { return null; } Point3D i; return ray.PlaneIntersection(position, normal, out i) ? (Point3D?)i : null; }
/// <summary> /// Unproject a point from the screen (2D) to a point on plane (3D) /// </summary> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="p"> /// The 2D point. /// </param> /// <param name="position"> /// plane position /// </param> /// <param name="normal"> /// plane normal /// </param> /// <returns> /// A 3D point. /// </returns> /// <remarks> /// Map window coordinates to object coordinates like gluUnProject. /// </remarks> public static Point3D?UnProject(Viewport3D viewport, Point p, Point3D position, Vector3D normal) { Ray3D ray = GetRay(viewport, p); if (ray == null) { return(null); } return(ray.PlaneIntersection(position, normal)); }
/// <summary> /// Gets the nearest point on the translation axis. /// </summary> /// <param name="position"> /// The position (in screen coordinates). /// </param> /// <param name="hitPlaneOrigin"> /// The hit plane origin (world coordinate system). /// </param> /// <param name="hitPlaneNormal"> /// The hit plane normal (world coordinate system). /// </param> /// <returns> /// The nearest point (world coordinates) or null if no point could be found. /// </returns> private Point3D?GetNearestPoint(Point position, Point3D hitPlaneOrigin, Vector3D hitPlaneNormal) { var hpp = this.GetHitPlanePoint(position, hitPlaneOrigin, hitPlaneNormal); if (hpp == null) { return(null); } var ray = new Ray3D(this.ToWorld(this.Position), this.ToWorld(this.Direction)); return(ray.GetNearest(hpp.Value)); }
/// <summary> /// Gets the nearest point on the translation axis. /// </summary> /// <param name="position"> /// The position (in screen coordinates). /// </param> /// <param name="hitPlaneOrigin"> /// The hit plane origin (world coordinate system). /// </param> /// <param name="hitPlaneNormal"> /// The hit plane normal (world coordinate system). /// </param> /// <returns> /// The nearest point (world coordinates) or null if no point could be found. /// </returns> private Point3D? GetNearestPoint(Point position, Point3D hitPlaneOrigin, Vector3D hitPlaneNormal) { var hpp = this.GetHitPlanePoint(position, hitPlaneOrigin, hitPlaneNormal); if (hpp == null) { return null; } var ray = new Ray3D(this.ToWorld(this.Position), this.ToWorld(this.Direction)); return ray.GetNearest(hpp.Value); }
/// <summary> /// Gets the intersection with the specified ray. /// </summary> /// <param name="ray">The ray.</param> /// <param name="result">The intersection point(s).</param> /// <returns>The intersection points sorted by distance from the ray origin.</returns> public bool RayIntersection(Ray3D ray, out Point3D[] result) { double cx = this.center.X; double cy = this.center.Y; double cz = this.center.Z; double r = this.radius; double x1 = ray.Origin.X; double y1 = ray.Origin.Y; double z1 = ray.Origin.Z; double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; // Quadratic solving double a = (dx * dx) + (dy * dy) + (dz * dz); double b = (2 * dx * (x1 - cx)) + (2 * dy * (y1 - cy)) + (2 * dz * (z1 - cz)); double c = (x1 * x1) + (y1 * y1) + (z1 * z1) + (cx * cx) + (cz * cz) + (cy * cy) - (2 * ((cy * y1) + (cz * z1) + (cx * x1))) - (r * r); // Discriminant double q = (b * b) - (4 * a * c); // We have at least one possible intersection if (q >= 0) { double q2 = Math.Sqrt((b * b) - (4 * a * c)); // First root double t1 = (-b + q2) / (2 * a); // Second root double t2 = (-b - q2) / (2 * a); if (t1 >= 0 && t2 >= 0 && !t1.Equals(t2)) { var i1 = new Point3D(x1 + (dx * t1), y1 + (dy * t1), z1 + (dz * t1)); var i2 = new Point3D(x1 + (dx * t2), y1 + (dy * t2), z1 + (dz * t2)); result = t1 < t2 ? new[] { i1, i2 } : new[] { i2, i1 }; return true; } if (t1 >= 0) { var i1 = new Point3D(x1 + (dx * t1), y1 + (dy * t1), z1 + (dz * t1)); result = new[] { i1 }; return true; } if (t2 >= 0) { var i2 = new Point3D(x1 + (dx * t2), y1 + (dy * t2), z1 + (dz * t2)); result = new[] { i2 }; return true; } } result = null; return false; }
/// <summary> /// Updates the cursor position. /// </summary> /// <param name="pt">The position of the cursor (in viewport coordinates).</param> private void UpdateCursorPosition(Point pt) { this.CursorOnElementPosition = this.FindNearestPoint(pt); this.CursorPosition = this.Viewport.UnProject(pt); // Calculate the cursor ray Point3D cursorNearPlanePoint; Point3D cursorFarPlanePoint; var ok = this.Viewport.Point2DtoPoint3D(pt, out cursorNearPlanePoint, out cursorFarPlanePoint); if (ok) { var ray = new Ray3D(cursorFarPlanePoint, cursorNearPlanePoint); this.CursorRay = ray; } else { this.CursorOnConstructionPlanePosition = null; this.CursorRay = null; } // Calculate the intersection between the construction plane and the cursor ray if (this.CursorRay != null) { this.CursorOnConstructionPlanePosition = this.ConstructionPlane.LineIntersection( this.CursorRay.Origin, this.CursorRay.Origin + this.CursorRay.Direction); } else { this.CursorOnConstructionPlanePosition = null; } // TODO: remove this code when the CurrentPosition property is removed #pragma warning disable 618 if (this.CursorOnElementPosition.HasValue) { this.CurrentPosition = this.CursorOnElementPosition.Value; } else { if (this.CursorPosition.HasValue) { this.CurrentPosition = this.CursorPosition.Value; } } #pragma warning restore 618 }
/// <summary> /// Gets the intersection with the specified ray. /// </summary> /// <param name="ray"> /// The ray. /// </param> /// <param name="result"> /// The result. /// </param> /// <returns> /// True if intersections were found. /// </returns> public bool RayIntersection(Ray3D ray, out Point3D[] result) { throw new NotImplementedException(); // http://www.devmaster.net/wiki/Ray-sphere_intersection }
/// <summary> /// Gets the intersection with the specified ray. /// </summary> /// <param name="ray">The ray.</param> /// <param name="result">The intersection point(s).</param> /// <returns>The intersection points sorted by distance from the ray origin.</returns> public bool RayIntersection(Ray3D ray, out Point3D[] result) { double cx = this.center.X; double cy = this.center.Y; double cz = this.center.Z; double r = this.radius; double x1 = ray.Origin.X; double y1 = ray.Origin.Y; double z1 = ray.Origin.Z; double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; // Quadratic solving double a = (dx * dx) + (dy * dy) + (dz * dz); double b = (2 * dx * (x1 - cx)) + (2 * dy * (y1 - cy)) + (2 * dz * (z1 - cz)); double c = (x1 * x1) + (y1 * y1) + (z1 * z1) + (cx * cx) + (cz * cz) + (cy * cy) - (2 * ((cy * y1) + (cz * z1) + (cx * x1))) - (r * r); // Discriminant double q = (b * b) - (4 * a * c); // We have at least one possible intersection if (q >= 0) { double q2 = Math.Sqrt((b * b) - (4 * a * c)); // First root double t1 = (-b + q2) / (2 * a); // Second root double t2 = (-b - q2) / (2 * a); if (t1 >= 0 && t2 >= 0 && !t1.Equals(t2)) { var i1 = new Point3D(x1 + (dx * t1), y1 + (dy * t1), z1 + (dz * t1)); var i2 = new Point3D(x1 + (dx * t2), y1 + (dy * t2), z1 + (dz * t2)); result = t1 < t2 ? new[] { i1, i2 } : new[] { i2, i1 }; return(true); } if (t1 >= 0) { var i1 = new Point3D(x1 + (dx * t1), y1 + (dy * t1), z1 + (dz * t1)); result = new[] { i1 }; return(true); } if (t2 >= 0) { var i2 = new Point3D(x1 + (dx * t2), y1 + (dy * t2), z1 + (dz * t2)); result = new[] { i2 }; return(true); } } result = null; return(false); }