| | | 1 | | //======================================================================= |
| | | 2 | | // ConePlaneRayEventSink.cs |
| | | 3 | | //======================================================================= |
| | | 4 | | // MIT License, Copyright (c) 2024-present David Oravsky (mrdav30) |
| | | 5 | | // See LICENSE file in the project root for full license information. |
| | | 6 | | //======================================================================= |
| | | 7 | | |
| | | 8 | | using System; |
| | | 9 | | |
| | | 10 | | namespace FixedMathSharp.Geometry; |
| | | 11 | | |
| | | 12 | | /// <summary>One borrowed exact output point or synchronous visitor; point-only replay does not solve unused exits.</sum |
| | | 13 | | internal ref struct ConePlaneRayEventSink |
| | | 14 | | { |
| | | 15 | | internal readonly ConePlaneRayEvent Target; |
| | | 16 | | internal readonly bool PointOnly; |
| | | 17 | | internal readonly int RequestedOrientation; |
| | | 18 | | private readonly ConePlaneRayPoint outputPoint; |
| | | 19 | | private readonly Span<ulong> outputRoot; |
| | | 20 | | private readonly ConePlaneRayEventVisitor? visitor; |
| | | 21 | | private readonly ConePlaneRayEventSource source; |
| | | 22 | | private readonly ConePlaneRayFrame frame; |
| | | 23 | | internal readonly ReadOnlySpan<RationalSegmentInterval> Clip; |
| | | 24 | | internal readonly ReadOnlySpan<WideAxis3> NativeSegment; |
| | 533861 | 25 | | internal bool IsStreaming => visitor != null; |
| | | 26 | | internal bool HasPoint; |
| | | 27 | | |
| | | 28 | | internal ConePlaneRayEventSink(ConePlaneRayEvent target, ConePlaneRayPoint point, Span<ulong> root, |
| | | 29 | | bool pointOnly = false, int requestedOrientation = 0, in ConePlaneRayEventSource source = default, |
| | | 30 | | in ConePlaneRayFrame frame = default, ReadOnlySpan<RationalSegmentInterval> clip = default) |
| | 278430 | 31 | | { Target = target; outputPoint = point; outputRoot = root; PointOnly = pointOnly; RequestedOrientation = requestedOr |
| | 389802 | 32 | | HasPoint = false; visitor = null; this.source = source; this.frame = frame; Clip = clip; NativeSegment = default |
| | | 33 | | |
| | | 34 | | internal ConePlaneRayEventSink(in ConePlaneRayEventSource source, in ConePlaneRayFrame frame, ConePlaneRayEventVisit |
| | | 35 | | ReadOnlySpan<RationalSegmentInterval> clip = default, ReadOnlySpan<WideAxis3> nativeSegment = default) |
| | 336 | 36 | | { this.source = source; this.frame = frame; this.visitor = visitor; Target = default; outputPoint = default; outputR |
| | 336 | 37 | | PointOnly = false; RequestedOrientation = 0; HasPoint = false; Clip = clip; NativeSegment = nativeSegment; } |
| | | 38 | | |
| | | 39 | | internal void GetSegment(in ConePlaneRayEventSource currentSource, in ConePlaneRayFrame currentFrame, out WideAxis3 |
| | | 40 | | { |
| | 7076 | 41 | | if (!NativeSegment.IsEmpty) { start = NativeSegment[0]; end = NativeSegment[1]; } |
| | 14008 | 42 | | else { start = currentFrame.Transform(currentSource.A); end = currentFrame.Transform(currentSource.B); } |
| | 7004 | 43 | | } |
| | | 44 | | |
| | | 45 | | internal bool Wants(ConePlaneRayEventKind kind) |
| | | 46 | | { |
| | 587320 | 47 | | if (!IsStreaming) return Target.Kind == kind; |
| | 822 | 48 | | if (source.IsSegment) |
| | 434 | 49 | | return kind == ConePlaneRayEventKind.EdgeEndpoint || kind == ConePlaneRayEventKind.EdgeSide |
| | 434 | 50 | | || kind == ConePlaneRayEventKind.EdgeStationary || kind == ConePlaneRayEventKind.UpperRim; |
| | 388 | 51 | | if (frame.Normal.X.IsZero && frame.Normal.Z.IsZero && !frame.Normal.Y.IsZero) |
| | 47 | 52 | | return kind == ConePlaneRayEventKind.Axis || kind == ConePlaneRayEventKind.LowerCircle; |
| | | 53 | | // The dispatcher invokes edge construction only for segment sources; |
| | | 54 | | // every remaining general-plane stratum belongs to its inventory. |
| | 341 | 55 | | return true; |
| | | 56 | | } |
| | 40358 | 57 | | internal bool Wants(in ConePlaneRayEvent descriptor) => IsStreaming ? Wants(descriptor.Kind) : Target.Matches(descri |
| | | 58 | | internal void Keep(in ConePlaneRayEvent descriptor, scoped ConePlaneRayPoint point, scoped ReadOnlySpan<ulong> root, |
| | | 59 | | scoped in ConePlaneRaySelection positive, scoped in ConePlaneRaySelection negative) |
| | | 60 | | { |
| | 5615 | 61 | | if (!Wants(descriptor)) return; |
| | 5515 | 62 | | if (!NativeSegment.IsEmpty) |
| | | 63 | | { |
| | 58 | 64 | | if (!ConePlaneRayEvents.ContainsNativeSegmentPoint(NativeSegment[0], NativeSegment[1], point, root, |
| | 83 | 65 | | Clip.IsEmpty ? default : Clip[0])) return; |
| | | 66 | | } |
| | 5466 | 67 | | else if (!Clip.IsEmpty && !ConePlaneRayEvents.IsPointInClip(source, frame, point, root, Clip[0])) return; |
| | 5481 | 68 | | if (visitor != null) |
| | | 69 | | { |
| | 275 | 70 | | visitor(source, frame, descriptor, point, root, positive, negative); |
| | 275 | 71 | | HasPoint = true; |
| | 275 | 72 | | return; |
| | | 73 | | } |
| | 5206 | 74 | | point.CopyTo(outputPoint); |
| | 10412 | 75 | | root.CopyTo(outputRoot); outputRoot[root.Length..].Clear(); |
| | 5206 | 76 | | HasPoint = true; |
| | 5206 | 77 | | } |
| | | 78 | | } |