/// <summary> /// Generates a square grid with a step of 1.0 /// </summary> /// <returns></returns> public static LineGeometry3D GenerateGrid(Vector3 plane, int min = 0, int max = 10) { var grid = new LineBuilder(); //int width = max - min; if (plane == Vector3.UnitX) { for (int i = min; i <= max; i++) { grid.AddLine(new Vector3(0, i, min), new Vector3(0, i, max)); grid.AddLine(new Vector3(0, min, i), new Vector3(0, max, i)); } } else if (plane == Vector3.UnitY) { for (int i = min; i <= max; i++) { grid.AddLine(new Vector3(i, 0, min), new Vector3(i, 0, max)); grid.AddLine(new Vector3(min, 0, i), new Vector3(max, 0, i)); } } else { for (int i = min; i <= max; i++) { grid.AddLine(new Vector3(i, min, 0), new Vector3(i, max, 0)); grid.AddLine(new Vector3(min, i, 0), new Vector3(max, i, 0)); } } return(grid.ToLineGeometry3D()); }
/// <summary> /// /// </summary> /// <param name="plane"></param> /// <param name="radius"></param> /// <param name="segments"></param> /// <returns></returns> public static LineGeometry3D GenerateCircle(Vector3 plane, float radius, int segments) { var bd = new LineBuilder(); bd.AddCircle(Vector3.Zero, plane, radius, segments); return(bd.ToLineGeometry3D()); }
/// <summary> /// /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> public void AddLine(Point3D p1, Point3D p2) { int i0 = positions.Count; this.positions.Add(p1); this.positions.Add(p2); this.lineListIndices.Add(i0); this.lineListIndices.Add(i0 + 1); }
/// <summary> /// /// </summary> /// <param name="ray"></param> /// <param name="t0"></param> /// <param name="t1"></param> /// <param name="sp"></param> /// <param name="tp"></param> /// <param name="sc"></param> /// <param name="tc"></param> /// <returns></returns> public static float GetRayToLineDistance( Ray ray, Vector3 t0, Vector3 t1, out Vector3 sp, out Vector3 tp, out float sc, out float tc) { var s0 = ray.Position; var s1 = ray.Position + ray.Direction; return(GetLineToLineDistance(s0, s1, t0, t1, out sp, out tp, out sc, out tc, true)); }
/// <summary> /// /// </summary> /// <param name="center"></param> /// <param name="xlength"></param> /// <param name="ylength"></param> /// <param name="zlength"></param> public void AddBox(Point3D center, double xlength, double ylength, double zlength) { int i0 = positions.Count; var dx = new Vector3D((float)xlength/2f, 0, 0); var dy = new Vector3D(0, (float)ylength/2f, 0); var dz = new Vector3D(0, 0, (float)zlength/2f); this.Add(true, center - dx - dy - dz, center + dx - dy - dz, center + dx + dy - dz, center - dx + dy - dz); this.Add(true, center - dx - dy + dz, center + dx - dy + dz, center + dx + dy + dz, center - dx + dy + dz); lineListIndices.AddRange(new[] { i0 + 0, i0 + 4, i0 + 1, i0 + 5, i0 + 2, i0 + 6, i0 + 3, i0 + 7 }); }
/// <summary> /// /// </summary> /// <param name="center"></param> /// <param name="xlength"></param> /// <param name="ylength"></param> /// <param name="zlength"></param> public void AddBox(Point3D center, double xlength, double ylength, double zlength) { int i0 = positions.Count; var dx = new Vector3D((float)xlength / 2f, 0, 0); var dy = new Vector3D(0, (float)ylength / 2f, 0); var dz = new Vector3D(0, 0, (float)zlength / 2f); this.Add(true, center - dx - dy - dz, center + dx - dy - dz, center + dx + dy - dz, center - dx + dy - dz); this.Add(true, center - dx - dy + dz, center + dx - dy + dz, center + dx + dy + dz, center - dx + dy + dz); lineListIndices.AddRange(new[] { i0 + 0, i0 + 4, i0 + 1, i0 + 5, i0 + 2, i0 + 6, i0 + 3, i0 + 7 }); }
/// <summary> /// Adds the circle. /// </summary> /// <param name="position">The position.</param> /// <param name="normal">The normal.</param> /// <param name="radius">The radius.</param> /// <param name="segments">The segments.</param> public void AddCircle(Vector3 position, Vector3 normal, float radius, int segments) { if (segments < 3) { throw new ArgumentNullException("too few segments, at least 3"); } normal.Normalize(); float sectionAngle = (float)(2.0 * Math.PI / segments); var start = new Vector3(radius, 0.0f, 0.0f); var current = new Vector3(radius, 0.0f, 0.0f); var next = new Vector3(0.0f, 0.0f, 0.0f); int posStart = positions.Count; positions.Add(current); int currIndex = posStart; for (int i = 1; i < segments; i++) { next.X = radius * (float)Math.Cos(i * sectionAngle); next.Z = radius * (float)Math.Sin(i * sectionAngle); current = next; positions.Add(current); lineListIndices.Add(currIndex); lineListIndices.Add(++currIndex); } lineListIndices.Add(currIndex); lineListIndices.Add(posStart); var axis = Vector3.Cross(Vector3.UnitY, normal); var transform = Matrix.Translation(position); if (axis.LengthSquared() > 1e-6) { axis.Normalize(); transform = Matrix.RotationAxis(axis, (float)Math.Acos(Vector3.Dot(Vector3.UnitY, normal))) * transform; } for (int i = posStart; i < positions.Count; ++i) { positions[i] = Vector3.TransformCoordinate(positions[i], transform); } }
/// <summary> /// ~7874015 tests per second, 3.36 times faster than GetRayToLineDistance() /// </summary> /// <param name="pt"></param> /// <param name="p0"></param> /// <param name="p1"></param> /// <param name="closest"></param> /// <param name="t"></param> /// <returns></returns> public static float GetPointToLineDistance2D(ref Vector3 pt, ref Vector3 p0, ref Vector3 p1, out Vector3 closest, out float t) { float dx = p1.X - p0.X; float dy = p1.Y - p0.Y; if (Math.Abs(dx) < float.Epsilon && Math.Abs(dy) < float.Epsilon) { // The points are too close together. closest = p0; dx = pt.X - p0.X; dy = pt.Y - p0.Y; t = 0f; return((float)Math.Sqrt(dx * dx + dy * dy)); } // Calculate scale factor t of intersection. t = ((pt.X - p0.X) * dx + (pt.Y - p0.Y) * dy) / (dx * dx + dy * dy); // Test, if t inside line bounds. if (t < 0) { closest = new Vector3(p0.X, p0.Y, p0.Z); t = 0f; dx = pt.X - p0.X; dy = pt.Y - p0.Y; } else if (t > 1) { closest = new Vector3(p1.X, p1.Y, p1.Z); t = 1f; dx = pt.X - p1.X; dy = pt.Y - p1.Y; } else { closest = new Vector3(p0.X + t * dx, p0.Y + t * dy, pt.Z); dx = pt.X - closest.X; dy = pt.Y - closest.Y; } return((float)Math.Sqrt(dx * dx + dy * dy)); }
public static LineGeometry3D GenerateGrid(Vector3 plane, int min0 = 0, int max0 = 10, int min1 = 0, int max1 = 10, int sizew = 1, int sizeh = 1) { var grid = new LineBuilder(); //int width = max - min; if (plane == Vector3.UnitX) { for (int i = min0; i <= max0; i += sizew) { grid.AddLine(new Vector3(0, i, min1), new Vector3(0, i, max1)); } for (int i = min1; i <= max1; i += sizeh) { grid.AddLine(new Vector3(0, min0, i), new Vector3(0, max0, i)); } } else if (plane == Vector3.UnitY) { for (int i = min0; i <= max0; i += sizew) { grid.AddLine(new Vector3(i, 0, min1), new Vector3(i, 0, max1)); } for (int i = min1; i <= max1; i += sizeh) { grid.AddLine(new Vector3(min0, 0, i), new Vector3(max0, 0, i)); } } else { for (int i = min0; i <= max0; i += sizew) { grid.AddLine(new Vector3(i, min1, 0), new Vector3(i, max1, 0)); } for (int i = min1; i <= max1; i += sizeh) { grid.AddLine(new Vector3(min0, i, 0), new Vector3(max0, i, 0)); } } return(grid.ToLineGeometry3D()); }
/// <summary> /// Source: http://geomalgorithms.com/a07-_distance.html /// ~2341920 tests per second</summary> /// <param name="s0"></param> /// <param name="s1"></param> /// <param name="t0"></param> /// <param name="t1"></param> /// <param name="sp"></param> /// <param name="tp"></param> /// <param name="sc"></param> /// <param name="tc"></param> /// <param name="sIsRay"></param> /// <returns></returns> public static float GetLineToLineDistance( Vector3 s0, Vector3 s1, Vector3 t0, Vector3 t1, out Vector3 sp, out Vector3 tp, out float sc, out float tc, bool sIsRay = false) { Vector3 u = s1 - s0; Vector3 v = t1 - t0; Vector3 w = s0 - t0; float a = Vector3.Dot(u, u); // always >= 0 float b = Vector3.Dot(u, v); float c = Vector3.Dot(v, v); // always >= 0 float d = Vector3.Dot(u, w); float e = Vector3.Dot(v, w); float D = a * c - b * b; // always >= 0 float sN, sD = D; // sc = sN / sD, default sD = D >= 0 float tN, tD = D; // tc = tN / tD, default tD = D >= 0 // compute the line parameters of the two closest points if (D < float.Epsilon) { // the lines are almost parallel sN = 0.0f; // force using point P0 on segment S1 sD = 1.0f; // to prevent possible division by 0.0 later tN = e; tD = c; } else { // get the closest points on the infinite lines sN = (b * e - c * d); tN = (a * e - b * d); if (!sIsRay) { if (sN < 0.0f) { // sc < 0 => the s=0 edge is visible sN = 0.0f; tN = e; tD = c; } else if (sN > sD) { // sc > 1 => the s=1 edge is visible sN = sD; tN = e + b; tD = c; } } } if (tN < 0.0f) { // tc < 0 => the t=0 edge is visible tN = 0.0f; // recompute sc for this edge if (-d < 0.0f) { sN = 0.0f; } else if (-d > a) { sN = sD; } else { sN = -d; sD = a; } } else if (tN > tD) { // tc > 1 => the t=1 edge is visible tN = tD; // recompute sc for this edge if ((-d + b) < 0.0f) { sN = 0; } else if ((-d + b) > a) { sN = sD; } else { sN = (-d + b); sD = a; } } // finally do the division to get sc and tc sc = (Math.Abs(sN) < float.Epsilon ? 0.0f : sN / sD); tc = (Math.Abs(tN) < float.Epsilon ? 0.0f : tN / tD); // get the difference of the two closest points sp = s0 + (sc * u); tp = t0 + (tc * v); var tv = sp - tp; return(tv.Length()); // return the closest distance }
public static global::SharpDX.Color4 ToColor4(this global::SharpDX.Vector3 vector, float w = 1f) { return(new global::SharpDX.Color4((float)vector.X, (float)vector.Y, (float)vector.Z, w)); }
/// <summary> /// /// </summary> /// <param name="plane"></param> /// <param name="radius"></param> /// <param name="segments"></param> /// <returns></returns> public static LineGeometry3D GenerateCircle(Vector3 plane, float radius, int segments) { if (segments < 3) { throw new ArgumentNullException("too few segments, at least 3"); } var circle = new LineBuilder(); float sectionAngle = (float)(2.0 * Math.PI / segments); if (plane == Vector3.UnitX) { Point3D start = new Point3D(0.0f, 0.0f, radius); Point3D current = new Point3D(0.0f, 0.0f, radius); Point3D next = new Point3D(0.0f, 0.0f, 0.0f); for (int i = 1; i < segments; i++) { next.Z = radius * (float)Math.Cos(i * sectionAngle); next.Y = radius * (float)Math.Sin(i * sectionAngle); circle.AddLine(current, next); current = next; } circle.AddLine(current, start); } else if (plane == Vector3.UnitY) { Point3D start = new Point3D(radius, 0.0f, 0.0f); Point3D current = new Point3D(radius, 0.0f, 0.0f); Point3D next = new Point3D(0.0f, 0.0f, 0.0f); for (int i = 1; i < segments; i++) { next.X = radius * (float)Math.Cos(i * sectionAngle); next.Z = radius * (float)Math.Sin(i * sectionAngle); circle.AddLine(current, next); current = next; } circle.AddLine(current, start); } else { Point3D start = new Point3D(0.0f, radius, 0.0f); Point3D current = new Point3D(0.0f, radius, 0.0f); Point3D next = new Point3D(0.0f, 0.0f, 0.0f); for (int i = 1; i < segments; i++) { next.Y = radius * (float)Math.Cos(i * sectionAngle); next.X = radius * (float)Math.Sin(i * sectionAngle); circle.AddLine(current, next); current = next; } circle.AddLine(current, start); } return(circle.ToLineGeometry3D()); }
public static global::SharpDX.Vector3 Normalized(this global::SharpDX.Vector3 vector) { vector.Normalize(); return(vector); }
/// <summary> /// Generates a square grid with a step of 1.0 /// </summary> /// <returns></returns> public static LineGeometry3D GenerateGrid(Vector3 plane, int min = 0, int max = 10) { var grid = new LineBuilder(); //int width = max - min; if (plane == Vector3.UnitX) { for (int i = min; i <= max; i++) { grid.AddLine(new Vector3(0, i, min), new Vector3(0, i, max)); grid.AddLine(new Vector3(0, min, i), new Vector3(0, max, i)); } } else if (plane == Vector3.UnitY) { for (int i = min; i <= max; i++) { grid.AddLine(new Vector3(i, 0, min), new Vector3(i, 0, max)); grid.AddLine(new Vector3(min, 0, i), new Vector3(max, 0, i)); } } else { for (int i = min; i <= max; i++) { grid.AddLine(new Vector3(i, min, 0), new Vector3(i, max, 0)); grid.AddLine(new Vector3(min, i, 0), new Vector3(max, i, 0)); } } return grid.ToLineGeometry3D(); }
/// <summary> /// Returns a line geometry of the axis-aligned bounding-box of the given mesh. /// </summary> /// <param name="mesh">Input mesh for the computation of the b-box</param> /// <returns></returns> public static LineGeometry3D GenerateBoundingBox(Vector3[] points) { var bb = global::SharpDX.BoundingBox.FromPoints(points); return GenerateBoundingBox(bb); }
/// <summary> /// Source: http://geomalgorithms.com/a07-_distance.html /// ~2341920 tests per second</summary> /// <param name="s0"></param> /// <param name="s1"></param> /// <param name="t0"></param> /// <param name="t1"></param> /// <param name="sp"></param> /// <param name="tp"></param> /// <param name="sc"></param> /// <param name="tc"></param> /// <param name="sIsRay"></param> /// <returns></returns> public static float GetLineToLineDistance( Vector3 s0, Vector3 s1, Vector3 t0, Vector3 t1, out Vector3 sp, out Vector3 tp, out float sc, out float tc, bool sIsRay = false) { Vector3 u = s1 - s0; Vector3 v = t1 - t0; Vector3 w = s0 - t0; float a = Vector3.Dot(u, u); // always >= 0 float b = Vector3.Dot(u, v); float c = Vector3.Dot(v, v); // always >= 0 float d = Vector3.Dot(u, w); float e = Vector3.Dot(v, w); float D = a * c - b * b; // always >= 0 float sN, sD = D; // sc = sN / sD, default sD = D >= 0 float tN, tD = D; // tc = tN / tD, default tD = D >= 0 // compute the line parameters of the two closest points if (D < float.Epsilon) { // the lines are almost parallel sN = 0.0f; // force using point P0 on segment S1 sD = 1.0f; // to prevent possible division by 0.0 later tN = e; tD = c; } else { // get the closest points on the infinite lines sN = (b * e - c * d); tN = (a * e - b * d); if (!sIsRay) { if (sN < 0.0f) { // sc < 0 => the s=0 edge is visible sN = 0.0f; tN = e; tD = c; } else if (sN > sD) { // sc > 1 => the s=1 edge is visible sN = sD; tN = e + b; tD = c; } } } if (tN < 0.0f) { // tc < 0 => the t=0 edge is visible tN = 0.0f; // recompute sc for this edge if (-d < 0.0f) { sN = 0.0f; } else if (-d > a) { sN = sD; } else { sN = -d; sD = a; } } else if (tN > tD) { // tc > 1 => the t=1 edge is visible tN = tD; // recompute sc for this edge if ((-d + b) < 0.0f) { sN = 0; } else if ((-d + b) > a) { sN = sD; } else { sN = (-d + b); sD = a; } } // finally do the division to get sc and tc sc = (Math.Abs(sN) < float.Epsilon ? 0.0f : sN / sD); tc = (Math.Abs(tN) < float.Epsilon ? 0.0f : tN / tD); // get the difference of the two closest points sp = s0 + (sc * u); tp = t0 + (tc * v); var tv = sp - tp; return tv.Length(); // return the closest distance }
/// <summary> /// /// </summary> /// <param name="ray"></param> /// <param name="t0"></param> /// <param name="t1"></param> /// <param name="sp"></param> /// <param name="tp"></param> /// <param name="sc"></param> /// <param name="tc"></param> /// <returns></returns> public static float GetRayToLineDistance( Ray ray, Vector3 t0, Vector3 t1, out Vector3 sp, out Vector3 tp, out float sc, out float tc) { var s0 = ray.Position; var s1 = ray.Position + ray.Direction; return GetLineToLineDistance(s0, s1, t0, t1, out sp, out tp, out sc, out tc, true); }
/// <summary> /// ~7874015 tests per second, 3.36 times faster than GetRayToLineDistance() /// </summary> /// <param name="pt"></param> /// <param name="p0"></param> /// <param name="p1"></param> /// <param name="closest"></param> /// <param name="t"></param> /// <returns></returns> public static float GetPointToLineDistance2D(ref Vector3 pt, ref Vector3 p0, ref Vector3 p1, out Vector3 closest, out float t) { float dx = p1.X - p0.X; float dy = p1.Y - p0.Y; if (Math.Abs(dx) < float.Epsilon && Math.Abs(dy) < float.Epsilon) { // The points are too close together. closest = p0; dx = pt.X - p0.X; dy = pt.Y - p0.Y; t = 0f; return (float)Math.Sqrt(dx * dx + dy * dy); } // Calculate scale factor t of intersection. t = ((pt.X - p0.X) * dx + (pt.Y - p0.Y) * dy) / (dx * dx + dy * dy); // Test, if t inside line bounds. if (t < 0) { closest = new Vector3(p0.X, p0.Y, p0.Z); t = 0f; dx = pt.X - p0.X; dy = pt.Y - p0.Y; } else if (t > 1) { closest = new Vector3(p1.X, p1.Y, p1.Z); t = 1f; dx = pt.X - p1.X; dy = pt.Y - p1.Y; } else { closest = new Vector3(p0.X + t * dx, p0.Y + t * dy, pt.Z); dx = pt.X - closest.X; dy = pt.Y - closest.Y; } return (float)Math.Sqrt(dx * dx + dy * dy); }
/// <summary> /// /// </summary> /// <param name="plane"></param> /// <param name="radius"></param> /// <param name="segments"></param> /// <returns></returns> public static LineGeometry3D GenerateCircle(Vector3 plane, float radius, int segments) { if (segments < 3) { throw new ArgumentNullException("too few segments, at least 3"); } var circle = new LineBuilder(); float sectionAngle = (float)(2.0 * Math.PI / segments); if (plane == Vector3.UnitX) { Point3D start = new Point3D(0.0f, 0.0f, radius); Point3D current = new Point3D(0.0f, 0.0f, radius); Point3D next = new Point3D(0.0f, 0.0f, 0.0f); for (int i = 1; i < segments; i++) { next.Z = radius * (float)Math.Cos(i * sectionAngle); next.Y = radius * (float)Math.Sin(i * sectionAngle); circle.AddLine(current, next); current = next; } circle.AddLine(current, start); } else if (plane == Vector3.UnitY) { Point3D start = new Point3D(radius, 0.0f, 0.0f); Point3D current = new Point3D(radius, 0.0f, 0.0f); Point3D next = new Point3D(0.0f, 0.0f, 0.0f); for (int i = 1; i < segments; i++) { next.X = radius * (float)Math.Cos(i * sectionAngle); next.Z = radius * (float)Math.Sin(i * sectionAngle); circle.AddLine(current, next); current = next; } circle.AddLine(current, start); } else { Point3D start = new Point3D(0.0f, radius, 0.0f); Point3D current = new Point3D(0.0f, radius, 0.0f); Point3D next = new Point3D(0.0f, 0.0f, 0.0f); for (int i = 1; i < segments; i++) { next.Y = radius * (float)Math.Cos(i * sectionAngle); next.X = radius * (float)Math.Sin(i * sectionAngle); circle.AddLine(current, next); current = next; } circle.AddLine(current, start); } return circle.ToLineGeometry3D(); }