public Vector3 ClosestCornerTo(Vector3 worldPos) { var lp = LocalFromWorldPoint(worldPos); var corner = PoseUtils.ScaleVector3(PoseUtils.Sign(lp), Primitive.vectorRadii); return(WorldFromLocalPoint(corner)); }
internal DistanceSample SampleDistanceVectorFromPointLocal(Vector3 localPos, ShapeSample shape) { if (verticesInXZ != null) { var polygon = verticesInXZ; var nearestPoint = localPos; if ((shape == ShapeSample.Fill) && GeometryUtils.PointInPolygon(localPos, polygon)) { nearestPoint.y = 0.0f; } else { nearestPoint = ClosetPointOnPolygonEdge(localPos, polygon); } var toSurf = (nearestPoint - localPos); return(new DistanceSample(toSurf.magnitude, toSurf)); } if (primitiveType == FieldPrimitiveType.Box) { // Note: C0 not C1 continuous if (shape == ShapeSample.Fill) { var nearest = PoseUtils.ScaleVector3(PoseUtils.Min(PoseUtils.Abs(localPos), vectorRadii), PoseUtils.Sign(localPos)); var b = PoseUtils.Abs(localPos) - (vectorRadii); var dist = Mathf.Max(b.x, Mathf.Max(b.y, b.z)); if (dist < 0.0f) { b = vectorRadii - PoseUtils.Abs(localPos); nearest = localPos; var nearestTip = PoseUtils.ScaleVector3(vectorRadii, PoseUtils.Sign(localPos)); if (PoseUtils.IsXTheMin(b)) { nearest.x = nearestTip.x; } else if (PoseUtils.IsYTheMin(b)) { nearest.y = nearestTip.y; } else { nearest.z = nearestTip.z; } } else { dist = (nearest - localPos).magnitude; } var toSurf = (nearest - localPos); return(new DistanceSample(dist, toSurf)); } else if (shape == ShapeSample.Edge) { var absLocal = PoseUtils.Abs(localPos); var absUnit = PoseUtils.Abs(PoseUtils.InvScaleVector3(localPos, vectorRadii) - Vector3.one); var absNearest = vectorRadii; if (PoseUtils.IsXTheMin(absUnit)) { absNearest = new Vector3(absLocal.x, vectorRadii.y, vectorRadii.z); } else if (PoseUtils.IsYTheMin(absUnit)) { absNearest = new Vector3(vectorRadii.x, absLocal.y, vectorRadii.z); } else { absNearest = new Vector3(vectorRadii.x, vectorRadii.y, absLocal.z); } var nearest = PoseUtils.ScaleVector3(absNearest, PoseUtils.Sign(localPos)); var toSurf = (nearest - localPos); var dist = toSurf.magnitude; return(new DistanceSample(dist, toSurf)); } else { throw new System.NotImplementedException("TODO:" + shape); } } else if (primitiveType == FieldPrimitiveType.Sphere) { var nearest = PoseUtils.ScaleVector3(localPos.normalized, vectorRadii); var dist = (localPos.magnitude - nearest.magnitude); return(new DistanceSample(dist, nearest - localPos)); } else if (primitiveType == FieldPrimitiveType.PlaneForward) { if (shape == ShapeSample.Edge) { throw new System.NotImplementedException("TODO: Plane+Edge"); } Vector3 nearest; var flipDistance = false; if ((shape == ShapeSample.Fill) && (localPos.z >= 0)) { nearest = new Vector3( Mathf.Clamp(localPos.x, -vectorRadii.x, vectorRadii.x), Mathf.Clamp(localPos.y, -vectorRadii.y, vectorRadii.y), Mathf.Clamp(localPos.z, -vectorRadii.z, vectorRadii.z) ); nearest.z = 0.0f; } else // if edge or if behind the plane { nearest = PoseUtils.ScaleVector3(vectorRadii, PoseUtils.Sign(localPos)); nearest.z = 0.0f; } var dist = (localPos.magnitude - nearest.magnitude) * (flipDistance ? -1.0f : 1.0f); return(new DistanceSample(dist, nearest - localPos)); } else if (primitiveType == FieldPrimitiveType.LineOnX) { var radius = vectorRadii.x; var fx = Mathf.Clamp(localPos.x, -radius, radius); var nearest = new Vector3(fx, 0, 0); var dist = nearest.magnitude; return(new DistanceSample(dist, nearest)); } else { throw new System.NotImplementedException("TODO."); } }