internal static void SampleLanesOneSideUpTo(Road road, SamplingStateRoad state, Side side, float sRoad, int outputIdx, ref NativeArray <PointSampleGlobal> samples, LaneType stopAtLane) { var lanes = GetLaneSectionSideUpTo(state.GetLaneSection(road, sRoad), side, stopAtLane); SampleLanesOneSide(road, state, side, sRoad, outputIdx, ref samples, lanes.Count()); }
// TODO: Refactor to separate lane sampling into helper which is agnostic to Side or LaneSection // Find all invocations of SampleLanes_____ and modify them to move the lanes array initialization // into the calling function internal static void SampleLanesOneSide(Road road, SamplingStateRoad state, Side side, float sRoad, int outputIdx, ref NativeArray <PointSampleGlobal> samples, int stopBeforeIdx = int.MaxValue) { var laneEdgeOffsetLocal = state.GetLaneOffset(road, sRoad); // TODO: Direct access to the Idx should be revoked and replaced with Getter methods var laneSection = state.GetLaneSection(road, sRoad); var lanes = GetLaneSectionSide(laneSection, side); if (!lanes.Any()) { return; } var numLanes = lanes.Count(); var laneIter = lanes.GetEnumerator(); var numSamplesPerLane = samples.Length / math.min(numLanes, stopBeforeIdx); var sLaneSection = sRoad - laneSection.sRoad; var geometrySample = state.GetGeometrySample(road, sRoad); for (var laneIdx = 0; laneIdx < numLanes && laneIdx < stopBeforeIdx; ++laneIdx) { // For some reason, in IEnumerables, the 'current' field actually returns the value at index-1 rather // than the actual current value, so we need to move the iterator first to set 'current' to the value // we'd expect laneIter.MoveNext(); var lane = laneIter.Current; var sampleLocal = BuildLaneSample(lane, laneEdgeOffsetLocal, sLaneSection); laneEdgeOffsetLocal = sampleLocal.position.y; var currentIdx = ComputeLaneSampleIdx(laneIdx, numSamplesPerLane, outputIdx); if (currentIdx >= samples.Length) { throw new Exception("Computed an out of range index."); } // The offset for the lane edge is measured along the normal of the reference line samples[currentIdx] = FromLocalToGlobal(geometrySample.pose, sampleLocal); } laneIter.Dispose(); }
internal static NativeArray <PointSampleGlobal> BuildSamplesFromRoadOutline( Road road, float samplesPerMeter, LaneType stopAtLane) { if (road.geometry.Count == 0) { throw new Exception($"The road {road} has no reference line."); } var numTotalSamples = ComputeNumSamplesForRoadLength(road.length, samplesPerMeter) * 2; var samplingState = new SamplingStateRoad(road, samplesPerMeter); var numSectionsLeft = road.laneSections.Max(s => s.leftLanes.Count()); var numSectionsRight = road.laneSections.Max(s => s.rightLanes.Count()); var leftSamplesTemp = new NativeArray <PointSampleGlobal>(numSectionsLeft, Allocator.Temp); var rightSamplesTemp = new NativeArray <PointSampleGlobal>(numSectionsRight, Allocator.Temp); var allSamples = new NativeArray <PointSampleGlobal>(numTotalSamples, Allocator.Temp); for (var sampleIdx = 0; sampleIdx < numTotalSamples / 2; sampleIdx++) { var sRoad = samplingState.sRoadLastComputed; // We intentionally do not pass state as a reference here, as each sampling pass will cover the same // segment of road. We would need to do some refactoring to sample all lanes for a given s-coordinate // in one call in order to use sampling state more effectively SampleLanesOneSideUpTo( road, samplingState, Side.Left, sRoad, 0, ref leftSamplesTemp, stopAtLane); SampleLanesOneSideUpTo( road, samplingState, Side.Right, sRoad, 0, ref rightSamplesTemp, stopAtLane); var currentSection = road.laneSections[samplingState.laneSectionIdx]; if (currentSection.rightLanes.Any()) { var sampledLanes = GetLaneSectionSideUpTo(samplingState.GetLaneSection(road, sRoad), Side.Right, stopAtLane); allSamples[sampleIdx] = sampledLanes.Any() ? rightSamplesTemp[sampledLanes.Count() - 1] : SampleCenter(road, samplingState, sRoad); } else { allSamples[sampleIdx] = SampleCenter(road, samplingState, sRoad); } // allSamples must be ordered to form a counter-clockwise outline, so left samples get added // in reverse order to the end of the array var leftIdx = numTotalSamples - 1 - sampleIdx; if (currentSection.leftLanes.Any()) { var sampledLanes = GetLaneSectionSideUpTo(samplingState.GetLaneSection(road, sRoad), Side.Left, stopAtLane); allSamples[leftIdx] = sampledLanes.Any() ? leftSamplesTemp[sampledLanes.Count() - 1] : SampleCenter(road, samplingState, sRoad); } else { allSamples[leftIdx] = SampleCenter(road, samplingState, sRoad); } var stepSucceeded = samplingState.Step(road); // We expect stepping to fail at the end of the current segment, but otherwise this would be a problem if (!stepSucceeded && sampleIdx * 2 + 2 != numTotalSamples) { Debug.LogWarning($"Reached end of road {road.roadId} early. Still have " + $"{numTotalSamples / 2 - sampleIdx - 1} samples to do."); } } leftSamplesTemp.Dispose(); rightSamplesTemp.Dispose(); return(allSamples); }