/// <summary> /// Precalculates speed factors for all the given profiles. /// </summary> public void CalculateFor(params Profile[] profiles) { lock (this) { // don't allow multiple threads to fill this cache at the same time. var newEdgeProfileFactors = new Dictionary <string, FactorAndSpeed[]>(_edgeProfileFactors); var edgeProfileFactors = new FactorAndSpeed[profiles.Length][]; for (var p = 0; p < profiles.Length; p++) { edgeProfileFactors[p] = new FactorAndSpeed[(int)_db.EdgeProfiles.Count]; } for (uint edgeProfile = 0; edgeProfile < _db.EdgeProfiles.Count; edgeProfile++) { var edgeProfileTags = _db.EdgeProfiles.Get(edgeProfile); for (var p = 0; p < profiles.Length; p++) { edgeProfileFactors[p][edgeProfile] = profiles[p].FactorAndSpeed(edgeProfileTags); } } for (var p = 0; p < profiles.Length; p++) { newEdgeProfileFactors[profiles[p].FullName] = edgeProfileFactors[p]; } _edgeProfileFactors = newEdgeProfileFactors; } }
/// <summary> /// Returns an isacceptable function using the cached data. /// </summary> public Func <GeometricEdge, bool> GetIsAcceptable(bool verifyCanStopOn, List <uint> closures, params IProfileInstance[] profileInstances) { if (!this.ContainsAll(profileInstances)) { throw new ArgumentException("Not all given profiles are supported."); } var cachedFactors = new FactorAndSpeed[profileInstances.Length][]; for (var p = 0; p < profileInstances.Length; p++) { cachedFactors[p] = _edgeProfileFactors[profileInstances[p].Profile.FullName]; } return((edge) => { // first check for closure if (closures.Contains(edge.Id)) { return false; } float distance; ushort edgeProfileId; Data.Edges.EdgeDataSerializer.Deserialize(edge.Data[0], out distance, out edgeProfileId); for (var i = 0; i < profileInstances.Length; i++) { var cachedFactor = cachedFactors[i][edgeProfileId]; if (cachedFactor.Value <= 0) { // edge is not accessible to this profile. return false; } if (verifyCanStopOn) { // check for a stopping point. if (!cachedFactor.CanStopOn()) { // can't use this edge as stopping point. return false; } } if (profileInstances[i].IsConstrained(cachedFactor.Constraints)) { // edge is constrained, vehicle too heavy or too big for example. return false; } } return true; }); }
/// <summary> /// Converts a factor definition for the given factor and speed. /// </summary> public static Factor ToFactor(this FactorAndSpeed factorAndSpeed) { if (factorAndSpeed.Direction >= 3) { return(new Profiles.Factor() { Direction = (short)(factorAndSpeed.Direction - 3), Value = factorAndSpeed.Value }); } return(new Profiles.Factor() { Direction = factorAndSpeed.Direction, Value = factorAndSpeed.Value }); }
/// <summary> /// Converts a speed definition for the given factor and speed. /// </summary> public static Speed ToSpeed(this FactorAndSpeed factorAndSpeed) { if (factorAndSpeed.Direction >= 3) { return(new Profiles.Speed() { Direction = (short)(factorAndSpeed.Direction - 3), Value = 1.0f / factorAndSpeed.SpeedFactor }); } return(new Profiles.Speed() { Direction = factorAndSpeed.Direction, Value = 1.0f / factorAndSpeed.SpeedFactor }); }
/// <summary> /// Precalculates speed factors for all the given profiles. /// </summary> public void CalculateFor(params Profile[] profiles) { var edgeProfileFactors = new FactorAndSpeed[profiles.Length][]; for (var p = 0; p < profiles.Length; p++) { edgeProfileFactors[p] = new FactorAndSpeed[(int)_db.EdgeProfiles.Count]; } for (uint edgeProfile = 0; edgeProfile < _db.EdgeProfiles.Count; edgeProfile++) { var edgeProfileTags = _db.EdgeProfiles.Get(edgeProfile); for (var p = 0; p < profiles.Length; p++) { edgeProfileFactors[p][edgeProfile] = profiles[p].FactorAndSpeed(edgeProfileTags); } } for (var p = 0; p < profiles.Length; p++) { _edgeProfileFactors[profiles[p].FullName] = edgeProfileFactors[p]; } }
/// <summary> /// Converts a factor definition for the given factor and speed. /// </summary> public static bool CanStopOn(this FactorAndSpeed factorAndSpeed) { return(factorAndSpeed.Direction < 3); }
/// <summary> /// Get a function to calculate properties for a set given edge attributes. /// </summary> /// <returns></returns> public sealed override FactorAndSpeed FactorAndSpeed(IAttributeCollection attributes) { lock (_script) { // build lua table. _attributesTable.Clear(); if (attributes == null || attributes.Count == 0) { return(Profiles.FactorAndSpeed.NoFactor); } foreach (var attribute in attributes) { _attributesTable.Set(attribute.Key, DynValue.NewString(attribute.Value)); } // call factor_and_speed function. _resultsTable.Clear(); _script.Call(_function, _attributesTable, _resultsTable); // get the results. var result = new FactorAndSpeed(); float val; if (!_resultsTable.TryGetFloat("speed", out val)) { val = 0; } if (val == 0) { return(Profiles.FactorAndSpeed.NoFactor); } result.SpeedFactor = 1.0f / (val / 3.6f); // 1/m/s if (_metric == ProfileMetric.TimeInSeconds) { // use 1/speed as factor. result.Value = result.SpeedFactor; } else if (_metric == ProfileMetric.DistanceInMeters) { // use 1 as factor. result.Value = 1; } else { // use a custom factor. if (!_resultsTable.TryGetFloat("factor", out val)) { val = 0; } result.Value = val; } if (!_resultsTable.TryGetFloat("direction", out val)) { val = 0; } result.Direction = (short)val; bool boolVal; if (!_resultsTable.TryGetBool("canstop", out boolVal)) { // default stopping everywhere. boolVal = true; } if (!boolVal) { result.Direction += 3; } return(result); } }