private static Sphere CreateSphereBarrier(IEnumerable <ITrackBoundary> trackObjects, [NotNull] Sphere sphere) { if (sphere == null) { throw new ArgumentNullException(nameof(sphere)); } var walls = trackObjects.OfType <Wall>().GroupBy(x => x.Corners.Select(y => Vector3D.AbsoluteValue(y - sphere.Center)).Min()) .OrderBy(x => x.Key).SelectMany(x => x).Take(3).ToList(); var corner = walls.Select(x => x.Corners).Aggregate((x, y) => x.Intersect(y).ToList()).Single(); var intersectionPoints = walls.Select(sphere.GetInterSection).ToList(); var barrier = new Plane(intersectionPoints[0], intersectionPoints[1], intersectionPoints[2]); var sign = barrier.DeterminePointPosition(corner); var checker = new PointChecker(barrier, sign); sphere.Checker = checker; return(sphere); }
private static Cylinder CalculateCylinder(Line first, Line second, Line wallLine, double radius) { var angle = Vector3D.Angle(first.Direction, second.Direction); var distance = Math.Sin(90.0.ToRadian()) / Math.Sin(angle / 2) * radius; var minimumWallDistance = Math.Sqrt(Math.Pow(distance, 2) - Math.Pow(radius, 2)); var referencePoint = wallLine.Contains(first.BasePoint) ? first.BasePoint : first.SecondPoint; var firstSign = first.BasePoint == referencePoint ? +1 : -1; var secondSign = second.BasePoint == referencePoint ? +1 : -1; var firstPoint = first.GetPointOnLine(referencePoint, firstSign * minimumWallDistance); var secondPoint = second.GetPointOnLine(referencePoint, secondSign * minimumWallDistance); var crossLine = new Line(firstPoint, secondPoint); var directLine = new Line(referencePoint, crossLine.ClosestPoint(referencePoint)); var top = directLine.GetPointOnLine(distance); var difference = top - referencePoint; var otherPoint = referencePoint == wallLine.BasePoint ? wallLine.SecondPoint : wallLine.BasePoint; var bottom = otherPoint + difference; var basLine = new Line(top, bottom); var reverseBase = new Line(bottom, top); var correctTop = basLine.GetPointOnLine(radius); var correctBottom = reverseBase.GetPointOnLine(radius); var wallHeight = Vector3D.AbsoluteValue(wallLine.SecondPoint - wallLine.BasePoint); var sign = otherPoint == wallLine.BasePoint ? -1 : +1; var bottomPoint = firstPoint + sign * wallHeight * (wallLine.SecondPoint - wallLine.BasePoint).Normalize(); var barrier = new Plane(firstPoint, secondPoint, bottomPoint); var checker = new PointChecker(barrier, barrier.DeterminePointPosition(referencePoint)); return(new Cylinder(correctTop, correctBottom, checker, radius)); }