/// <summary> /// Generates point samples from a road description extended by a specified distance /// </summary> /// <param name="extensionDistance">Offset applied to the beginning and end of road segment polygons. Increases /// the likelihood of polygon overlap to encourage the creation of one contiguous road network polygon.</param> public static void BuildSamplesFromRoadOutlineWithExtensionDistance( EcsRoadData road, float samplesPerMeter, float extensionDistance, NativeSlice <PointSampleGlobal> samplesOut) { BuildSamplesFromRoadOutline(road, samplesPerMeter, samplesOut); UpdateWithExtensionDistance(extensionDistance, samplesOut); }
internal static void BuildSamplesFromRoadOutline(EcsRoadData road, float samplesPerMeter, NativeSlice <PointSampleGlobal> allSamples) { if (road.ecsGeometries.Length == 0) { throw new Exception($"The road {road} has no reference line."); } var numTotalSamples = ComputeSampleCountForRoadOutline(road.ecsRoad, samplesPerMeter); if (numTotalSamples > allSamples.Length) { throw new ArgumentException("sample NativeSlice is not large enough to hold all the samples. Use ComputeSampleCountForRoadOutline to determine the proper number of samples.", nameof(allSamples)); } var samplingState = new SamplingStateEcsRoad(road, samplesPerMeter); //var numSectionsLeft = Max(road.ecsLaneSections, s => s.LeftLaneCount); //var numSectionsRight = Max(road.ecsLaneSections, s => s.RightLaneCount); int maxValue = int.MinValue; foreach (var laneSection in road.ecsLaneSections) { maxValue = math.max(maxValue, laneSection.LeftLaneCount); } var numSectionsLeft = maxValue; int maxValue1 = int.MinValue; foreach (var laneSection1 in road.ecsLaneSections) { maxValue1 = math.max(maxValue1, laneSection1.RightLaneCount); } var numSectionsRight = maxValue1; var leftSamplesTemp = new NativeArray <PointSampleGlobal>(numSectionsLeft, Allocator.Temp); var rightSamplesTemp = new NativeArray <PointSampleGlobal>(numSectionsRight, 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 SampleLanesOneSide(road, samplingState, Side.Left, sRoad, 0, ref leftSamplesTemp); SampleLanesOneSide(road, samplingState, Side.Right, sRoad, 0, ref rightSamplesTemp); var currentSection = road.ecsLaneSections[samplingState.laneSectionIdx]; allSamples[sampleIdx] = currentSection.RightLaneCount > 0 ? rightSamplesTemp[currentSection.RightLaneCount - 1] : 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 allSamples[numTotalSamples - 1 - sampleIdx] = currentSection.LeftLaneCount > 0 ? leftSamplesTemp[currentSection.LeftLaneCount - 1] : 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.ecsRoad.name} early. Still have " + $"{numTotalSamples / 2 - sampleIdx - 1} samples to do."); } } leftSamplesTemp.Dispose(); rightSamplesTemp.Dispose(); }
public EcsLaneSection GetLaneSection(EcsRoadData road, float sRoad) { sRoadCurrent = sRoad; CheckStateAndUpdate(road); return(road.ecsLaneSections[laneSectionIdx]); }
public void MoveToSCoordinate(EcsRoadData road, float sRoad) { sRoadCurrent = sRoad; CheckStateAndUpdate(road); }
public PointSampleGlobal GetGeometrySample(EcsRoadData road, float sRoad) { sRoadCurrent = sRoad; CheckStateAndUpdate(road); return(geometrySample); }