/// <summary> /// Tests a simple way read/write operation. /// </summary> /// <param name="cache"></param> public void DoOsmDataCacheTestWay(OsmDataCache cache) { Way way = Way.Create(1, new TagsCollection( Tag.Create("way", "yes")), 1, 2); // test invalid stuff. Assert.Throws <ArgumentNullException>(() => cache.AddWay(null)); Assert.Throws <Exception>(() => cache.AddWay(new Way())); Assert.IsNull(cache.GetWay(way.Id.Value)); cache.AddWay(way); Assert.IsTrue(cache.ContainsWay(way.Id.Value)); Way readWay = cache.GetWay(way.Id.Value); Assert.IsNotNull(readWay); Assert.AreEqual(1, readWay.Id.Value); Assert.IsNotNull(way.Tags); Assert.AreEqual(1, way.Tags.Count); Assert.AreEqual("yes", way.Tags["way"]); Assert.IsTrue(cache.TryGetWay(way.Id.Value, out readWay)); Assert.IsNotNull(readWay); Assert.AreEqual(1, readWay.Id.Value); Assert.IsNotNull(way.Tags); Assert.AreEqual(1, way.Tags.Count); Assert.AreEqual("yes", way.Tags["way"]); Assert.IsTrue(cache.RemoveWay(way.Id.Value)); Assert.IsFalse(cache.ContainsWay(way.Id.Value)); Assert.IsFalse(cache.RemoveWay(way.Id.Value)); }
/// <summary> /// Adds a given way. /// </summary> /// <param name="way"></param> public override void AddWay(Way way) { if (!_preIndexMode && _waysToCache != null && _waysToCache.Contains(way.Id.Value)) { // cache this way? _dataCache.AddWay(way); } // initialize the way interpreter. if (_interpreter.EdgeInterpreter.IsRoutable(way.Tags)) { // the way is a road. if (_preIndexMode) { // index only relevant nodes. if (way.Nodes != null) { foreach (long node in way.Nodes) { if (_preIndex.Contains(node)) { _usedTwiceOrMore.Add(node); } else { _preIndex.Add(node); // node is relevant. } } } } else { // add the forward edges. //if (!interpreter.IsOneWayReverse()) if (true) // add backward edges too! { // loop over all edges. if (way.Nodes != null && way.Nodes.Count > 1) { // way has at least two nodes. if (this.CalculateIsTraversable(_interpreter.EdgeInterpreter, _tagsIndex, way.Tags)) { // the edge is traversable, add the edges. uint?from = this.AddRoadNode(way.Nodes[0]); for (int idx = 1; idx < way.Nodes.Count; idx++) { // the to-node. uint?to = this.AddRoadNode(way.Nodes[idx]); // add the edge(s). if (from.HasValue && to.HasValue) { // add a road edge. if (!this.AddRoadEdge(way.Tags, true, from.Value, to.Value)) { // add the reverse too if it has been indicated that this was needed. this.AddRoadEdge(way.Tags, false, to.Value, from.Value); } } from = to; // the to node becomes the from. } } } } } } }
/// <summary> /// Tests the clear functionality on the datacache. /// </summary> /// <param name="cache"></param> public void DoOsmDataCacheTestClear(OsmDataCache cache) { Node node = Node.Create(1, new TagsCollection( Tag.Create("node", "yes")), 1, 2); Way way = Way.Create(1, new TagsCollection( Tag.Create("way", "yes")), 1, 2); Relation relation = Relation.Create(1, new TagsCollection( Tag.Create("relation", "yes")), RelationMember.Create(1, "something", OsmGeoType.Node)); cache.AddNode(node); cache.AddWay(way); cache.AddRelation(relation); Assert.IsTrue(cache.ContainsNode(node.Id.Value)); Assert.IsTrue(cache.ContainsWay(way.Id.Value)); Assert.IsTrue(cache.ContainsRelation(relation.Id.Value)); cache.Clear(); Assert.IsFalse(cache.ContainsNode(node.Id.Value)); Assert.IsFalse(cache.ContainsWay(way.Id.Value)); Assert.IsFalse(cache.ContainsRelation(relation.Id.Value)); }
/// <summary> /// Adds a given way. /// </summary> /// <param name="way"></param> public override void AddWay(Way way) { if (!_preIndexMode && _waysToCache != null && _waysToCache.Contains(way.Id.Value)) { // cache this way? _dataCache.AddWay(way); } // initialize the way interpreter. if (_interpreter.EdgeInterpreter.IsRoutable(way.Tags)) { // the way is a road. if (_preIndexMode) { // index relevant and used nodes. if (way.Nodes != null) { // this way has nodes. // add new routable tags type. var routableWayTags = new TagsCollection(way.Tags); routableWayTags.RemoveAll(x => { return(!_interpreter.IsRelevantRouting(x.Key) && !Vehicle.IsRelevantForOneOrMore(x.Key)); }); if (_storeTags) { _tagsIndex.Add(routableWayTags); } int wayNodesCount = way.Nodes.Count; for (int idx = 0; idx < wayNodesCount; idx++) { var node = way.Nodes[idx]; if (_preIndex.Contains(node)) { // node is relevant. _relevantNodes.Add(node); } else { // node is used. _preIndex.Add(node); } } if (wayNodesCount > 0) { // first node is always relevant. _relevantNodes.Add(way.Nodes[0]); if (wayNodesCount > 1) { // last node is always relevant. _relevantNodes.Add(way.Nodes[wayNodesCount - 1]); } } } } else { // add actual edges. if (way.Nodes != null && way.Nodes.Count > 1) { // way has at least two nodes. if (this.CalculateIsTraversable(_interpreter.EdgeInterpreter, _tagsIndex, way.Tags)) { // the edge is traversable, add the edges. uint? from = this.AddRoadNode(way.Nodes[0]); long fromNodeId = way.Nodes[0]; List <long> intermediates = new List <long>(); for (int idx = 1; idx < way.Nodes.Count; idx++) { // the to-node. long currentNodeId = way.Nodes[idx]; if (!_collectIntermediates || _relevantNodes.Contains(currentNodeId) || idx == way.Nodes.Count - 1) { // node is an important node. uint?to = this.AddRoadNode(currentNodeId); long toNodeId = currentNodeId; // add the edge(s). if (from.HasValue && to.HasValue) { // add a road edge. while (from.Value == to.Value) { if (intermediates.Count > 0) { uint?dummy = this.AddRoadNode(intermediates[0]); intermediates.RemoveAt(0); if (dummy.HasValue && from.Value != dummy.Value) { this.AddRoadEdge(way.Tags, from.Value, dummy.Value, null); from = dummy; } } else { // no use to continue. break; } } // build coordinates. var intermediateCoordinates = new List <GeoCoordinateSimple>(intermediates.Count); for (int coordIdx = 0; coordIdx < intermediates.Count; coordIdx++) { ICoordinate coordinate; if (!_coordinates.TryGet(intermediates[coordIdx], out coordinate)) { break; } intermediateCoordinates.Add(new GeoCoordinateSimple() { Latitude = coordinate.Latitude, Longitude = coordinate.Longitude }); } if (intermediateCoordinates.Count == intermediates.Count && from.Value != to.Value) { // all coordinates have been found. this.AddRoadEdge(way.Tags, from.Value, to.Value, intermediateCoordinates); } } // if this way has a restriction save the collapsed nodes information. if (_restricedWays.Contains(way.Id.Value) && to.HasValue && from.HasValue) { // loop over all intermediates and save. var collapsedInfo = new KeyValuePair <KeyValuePair <long, uint>, KeyValuePair <long, uint> >( new KeyValuePair <long, uint>(fromNodeId, from.Value), new KeyValuePair <long, uint>(toNodeId, to.Value)); foreach (var intermedidate in intermediates) { _collapsedNodes[intermedidate] = collapsedInfo; } } from = to; // the to node becomes the from. intermediates.Clear(); } else { // this node is just an intermediate. intermediates.Add(currentNodeId); } } } } } } }
/// <summary> /// Moves to the next object. /// </summary> /// <returns></returns> public override bool MoveNext() { if (!_cachingDone) { // first seek & cache. this.Seek(); _cachingDone = true; } while (_simpleSource.MoveNext()) { // there is data. OsmGeo currentSimple = _simpleSource.Current(); switch (currentSimple.Type) { case OsmGeoType.Node: // create complete version. _current = currentSimple as Node; if (_current != null && _current.Tags == null) { // make sure nodes have a default tag collection that is empty not null. _current.Tags = new OsmSharp.Collections.Tags.TagsCollection(); } if (_nodesToInclude.Contains(currentSimple.Id.Value)) { // node needs to be cached. _dataCache.AddNode(currentSimple as Node); _nodesToInclude.Remove(currentSimple.Id.Value); } break; case OsmGeoType.Way: // create complete way. _current = CompleteWay.CreateFrom(currentSimple as Way, _dataCache); if (_waysToInclude.Contains(currentSimple.Id.Value)) { // keep the way because it is needed later on. _dataCache.AddWay(currentSimple as Way); _waysToInclude.Remove(currentSimple.Id.Value); } else { // only report that the nodes have been used when the way can be let-go. Way way = currentSimple as Way; if (way.Nodes != null) { // report usage. way.Nodes.ForEach(x => this.ReportNodeUsage(x)); } } break; case OsmGeoType.Relation: // create complate relation. _current = CompleteRelation.CreateFrom(currentSimple as Relation, _dataCache); if (!_relationsToInclude.Contains(currentSimple.Id.Value)) { // only report relation usage when the relation can be let go. Relation relation = currentSimple as Relation; if (relation.Members != null) { foreach (RelationMember member in relation.Members) { switch (member.MemberType.Value) { case OsmGeoType.Node: this.ReportNodeUsage(member.MemberId.Value); break; case OsmGeoType.Way: this.ReportWayUsage(member.MemberId.Value); break; case OsmGeoType.Relation: this.ReportRelationUsage(member.MemberId.Value); break; } } } } break; } if (_current != null) { // only return complete objects. return(true); } } return(false); }
/// <summary> /// Moves to the next object. /// </summary> /// <returns></returns> private bool DoMoveNext() { if (!_cachingDone) { // first seek & cache. this.Seek(); this.CacheRelations(); _cachingDone = true; } if (this.Source.MoveNext()) { // there is data. OsmGeo currentSimple = this.Source.Current(); // make sure the object needs to be included. while (!this.IsChild(currentSimple) && !this.Include(currentSimple)) { // don't include this object! if (!this.Source.MoveNext()) { // oeps no more data! return(false); } currentSimple = this.Source.Current(); } switch (currentSimple.Type) { case OsmGeoType.Node: // create complete version. _current = currentSimple; if (_nodesToInclude.Contains(currentSimple.Id.Value)) { // node needs to be cached. _dataCache.AddNode(currentSimple as Node); _nodesToInclude.Remove(currentSimple.Id.Value); } break; case OsmGeoType.Way: // create complete way. _current = currentSimple; if (_waysToInclude.Contains(currentSimple.Id.Value)) { // keep the way because it is needed later on. _dataCache.AddWay(currentSimple as Way); _waysToInclude.Remove(currentSimple.Id.Value); } else { // only report that the nodes have been used when the way can be let-go. Way way = currentSimple as Way; if (way.Nodes != null) { // report usage. way.Nodes.ForEach(x => this.ReportNodeUsage(x)); } } break; case OsmGeoType.Relation: // create complate relation. _current = currentSimple; if (!_relationsToInclude.Contains(currentSimple.Id.Value)) { // only report relation usage when the relation can be let go. Relation relation = currentSimple as Relation; if (relation.Members != null) { foreach (RelationMember member in relation.Members) { switch (member.MemberType.Value) { case OsmGeoType.Node: this.ReportNodeUsage(member.MemberId.Value); break; case OsmGeoType.Way: this.ReportWayUsage(member.MemberId.Value); break; case OsmGeoType.Relation: this.ReportRelationUsage(member.MemberId.Value); break; } } } } break; } return(true); } return(false); }
/// <summary> /// Moves to the next object. /// </summary> /// <returns></returns> public override bool MoveNext() { if (!_cachingDone) { // first seek & cache. this.Seek(); this.CacheRelations(); _cachingDone = true; } while (_simpleSource.MoveNext()) { // there is data. OsmGeo currentSimple = _simpleSource.Current(); if (currentSimple.Id == 198214128 || currentSimple.Id == 1014892489) { System.Diagnostics.Debug.WriteLine(""); } switch (currentSimple.Type) { case OsmGeoType.Node: // create complete version. _current = CompleteNode.CreateFrom(currentSimple as Node); if (_nodesToInclude.Contains(currentSimple.Id.Value)) { // node needs to be cached. _dataCache.AddNode(currentSimple as Node); _nodesToInclude.Remove(currentSimple.Id.Value); } break; case OsmGeoType.Way: // create complete way. _current = CompleteWay.CreateFrom(currentSimple as Way, _dataCache); if (_waysToInclude.Contains(currentSimple.Id.Value)) { // keep the way because it is needed later on. _dataCache.AddWay(currentSimple as Way); _waysToInclude.Remove(currentSimple.Id.Value); } else { // only report that the nodes have been used when the way can be let-go. Way way = currentSimple as Way; if (way.Nodes != null) { // report usage. way.Nodes.ForEach(x => this.ReportNodeUsage(x)); } } break; case OsmGeoType.Relation: // create complate relation. _current = CompleteRelation.CreateFrom(currentSimple as Relation, _dataCache); if (!_relationsToInclude.Contains(currentSimple.Id.Value)) { // only report relation usage when the relation can be let go. Relation relation = currentSimple as Relation; if (relation.Members != null) { foreach (RelationMember member in relation.Members) { switch (member.MemberType.Value) { case OsmGeoType.Node: this.ReportNodeUsage(member.MemberId.Value); break; case OsmGeoType.Way: this.ReportWayUsage(member.MemberId.Value); break; case OsmGeoType.Relation: this.ReportRelationUsage(member.MemberId.Value); break; } } } } break; } if (_current != null) { // only return complete objects. return(true); } } return(false); }