public bool HitsCircle(Circle3d circle, double tmin, double tmax, ref RayHit3d hit) { var dc = circle.Normal.Dot(Direction); var dw = circle.Normal.Dot(circle.Center - Origin); // If parallel to plane if (dc == 0.0) { return(false); } var t = dw / dc; if (!ComputeHit(t, tmin, tmax, ref hit)) { return(false); } if (V3d.Distance(hit.Point, circle.Center) > circle.Radius) { hit.Point = V3d.NaN; hit.T = tmax; return(false); } return(true); }
// searches for oversized triangles and removes and adds all 3 vertex indices to invalid point list // (if one triangle side > maxTriangleSize => skip whole triangle) public static int[] GetAllPositionsFromOversizedTriangles(int[] invalidpositions, VertexGeometry vg, float maxTriangleSize) { var invalidPoints = new List <int>(invalidpositions); foreach (var t in vg.Triangles) { V3d p0, p1, p2; t.GetVertexPositions(out p0, out p1, out p2); if (p0.IsNaN || p1.IsNaN || p2.IsNaN) { continue; } double dist_p0p1 = V3d.Distance(p0, p1); double dist_p0p2 = V3d.Distance(p0, p2); double dist_p1p2 = V3d.Distance(p1, p2); if ((dist_p0p1 > maxTriangleSize) || (dist_p0p2 > maxTriangleSize) || (dist_p1p2 > maxTriangleSize)) { foreach (var index in t.VertexIndices) { if (!Array.Exists(invalidPoints.ToArray(), x => x == index)) { invalidPoints.Add(index); } } } } return(invalidPoints.ToArray()); }
public static double GetMinimalDistance(V3d p, V3d position, V3d direction, double majorRadius, double minorRadius) { var plane = new Plane3d(direction, position); var planePoint = p.GetClosestPointOn(plane); var distanceOnPlane = (V3d.Distance(planePoint, position) - majorRadius).Abs(); var distanceToCircle = (V3d.DistanceSquared(planePoint, p) + distanceOnPlane.Square()).Sqrt(); return((distanceToCircle - minorRadius).Abs()); }
public V3d GetClosestPoint(V3d point) { var ray = new Ray3d(Origin, Direction); var cp = point.GetClosestPointOn(ray); var radius = GetRadius(GetHeight(point)); var dir = (point - cp).Normalized * radius; var p0 = cp + dir; var p1 = point.GetClosestPointOn(new Ray3d(Origin, (p0 - Origin).Normalized)); return((V3d.Distance(point, p1) < V3d.Distance(point, p0)) ? p1 : p0); }
/// <summary> /// Gets Triangle Set loaded from AaraData and transformed to global space. /// Triangles side length < maxTriiangleSize /// </summary> public static TriangleSet LoadPatchTriangleSetWithoutOversizedTriangles(PatchFileInfo info, string basePath, PositionsType posType, float maxTriangleSize = float.PositiveInfinity) { var vg = LoadPatch(info, basePath, posType, false, false, false, false); if (vg == null) { return(new TriangleSet()); } vg.Transform( posType == PositionsType.V3dPositions ? info.Local2Global : info.Local2Global2d); var triangles = vg.Triangles .Where(x => !x.Point0.Position.IsNaN && !x.Point1.Position.IsNaN && !x.Point2.Position.IsNaN && (V3d.Distance(x.Point0.Position, x.Point1.Position) < maxTriangleSize) && (V3d.Distance(x.Point0.Position, x.Point2.Position) < maxTriangleSize) && (V3d.Distance(x.Point1.Position, x.Point2.Position) < maxTriangleSize)) .Select(x => x.ToTriangle3d()); return(new TriangleSet(triangles)); }
/// <summary> /// if zero, point is located on cone /// </summary> public double GetDistance(V3d point) { return(V3d.Distance(point, GetClosestPoint(point))); }
/// <summary> /// if zero, point is located on cone /// </summary> public double GetDistance(V3d point) => V3d.Distance(point, GetClosestPoint(point));
public bool HitsCylinder(Cylinder3d cylinder, double tmin, double tmax, ref RayHit3d hit) { var axisDir = cylinder.Axis.Direction.Normalized; // Vector Cyl.P0 -> Ray.Origin var op = Origin - cylinder.P0; // normal RayDirection - CylinderAxis var normal = Direction.Cross(axisDir); var unitNormal = normal.Normalized; // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis var normal2 = op.Cross(axisDir); var t = -normal2.Dot(unitNormal) / normal.Length; var radius = cylinder.Radius; if (cylinder.DistanceScale != 0) { // cylinder gets bigger, the further away it is var pnt = GetPointOnRay(t); var dis = V3d.Distance(pnt, this.Origin); radius = ((cylinder.Radius / cylinder.DistanceScale) * dis) * 2; } // between enitre rays (caps are ignored) var shortestDistance = Fun.Abs(op.Dot(unitNormal)); if (shortestDistance <= radius) { var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length); var t1 = t - s; // first hit of Cylinder shell var t2 = t + s; // second hit of Cylinder shell if (t1 > tmin && t1 < tmax) { tmin = t1; } if (t2 < tmax && t2 > tmin) { tmax = t2; } hit.T = t1; hit.Point = GetPointOnRay(t1); // check if found point is outside of Cylinder Caps var bottomPlane = new Plane3d(cylinder.Circle0.Normal, cylinder.Circle0.Center); var topPlane = new Plane3d(cylinder.Circle1.Normal, cylinder.Circle1.Center); var heightBottom = bottomPlane.Height(hit.Point); var heightTop = topPlane.Height(hit.Point); // t1 lies outside of caps => find closest cap hit if (heightBottom > 0 || heightTop > 0) { hit.T = tmax; // intersect with bottom Cylinder Cap var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit); // intersect with top Cylinder Cap var topHit = HitsPlane(topPlane, tmin, tmax, ref hit); // hit still close enough to cylinder axis? var distance = cylinder.Axis.Ray3d.GetMinimalDistanceTo(hit.Point); if (distance <= radius && (bottomHit || topHit)) { return(true); } } else { return(true); } } hit.T = tmax; hit.Point = V3d.NaN; return(false); }
// searches for oversized triangles and adds only invalid indices to invalid point list // (keep vertex indices for triangle side < maxTriangleSize) public static int[] GetInvalidPositionsFromOversizedTriangles(int[] invalidpositions, VertexGeometry vg, float maxTriangleSize) { var invalidPoints = new List <int>(invalidpositions); foreach (var t in vg.Triangles) { V3d p0, p1, p2; t.GetVertexPositions(out p0, out p1, out p2); if (p0.IsNaN || p1.IsNaN || p2.IsNaN) { continue; } List <V3d> vertexlist = new List <V3d>(); int p0_counter = 0; int p1_counter = 0; int p2_counter = 0; if (V3d.Distance(p0, p1) > maxTriangleSize) { vertexlist.Add(p0); vertexlist.Add(p1); } if (V3d.Distance(p0, p2) > maxTriangleSize) { vertexlist.Add(p0); vertexlist.Add(p2); } if (V3d.Distance(p1, p2) > maxTriangleSize) { vertexlist.Add(p1); vertexlist.Add(p2); } foreach (var p in vertexlist) { if (p == p0) { p0_counter++; } if (p == p1) { p1_counter++; } if (p == p2) { p2_counter++; } } if ((p0_counter > 1) && (!Array.Exists(invalidPoints.ToArray(), x => x == t.VertexIndex0))) { invalidPoints.Add(t.VertexIndex0); } if ((p1_counter > 1) && (!Array.Exists(invalidPoints.ToArray(), x => x == t.VertexIndex1))) { invalidPoints.Add(t.VertexIndex1); } if ((p2_counter > 1) && (!Array.Exists(invalidPoints.ToArray(), x => x == t.VertexIndex2))) { invalidPoints.Add(t.VertexIndex2); } } return(invalidPoints.ToArray()); }