using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using ISM4IaRouteplanner.Parser; using ISM4IaRouteplanner.Algoritmes; using ISM4IaRouteplanner.GFX; namespace ISM4IaRouteplanner.Data { public static class DataStorage { #region Attributes of DataStorage /// /// Dictionary of sections called cities /// public static Dictionary Cities { get; set; } /// /// Temporary dictionary of edges for use in linking /// private static Dictionary tmpEdges; /// /// Temporary dictionary of nodes for use in linking /// private static Dictionary tmpNodes; /// /// Temporary dictionary for the centrum points /// private static Dictionary tmpCentrum; /// /// List with all areas which can be used for drawing areas /// public static List listArea = new List(); /// /// List of Points of Interest /// public static List listPetrolStation = new List(); public static List listParkingGarage = new List(); public static List listHotel = new List(); public static List listRestaurant = new List(); public static List listTouristInformationOffice = new List(); public static List listMuseum = new List(); public static List listTheatre = new List(); public static List listHospital = new List(); public static List listPoliceStation = new List(); public static List listPostOffice = new List(); public static List listZoo = new List(); public static List listPanoramicView = new List(); public static List listCampingGround = new List(); public static List listSchool = new List(); public static List listImportantTouristAttraction = new List(); public static List listRailwayStation = new List(); #endregion #region Methods of Location /// /// Navigate from 1 location to another with the shortest path available. /// /// Leon Koppel 17-05-11 /// public static Route Navigate(List locations, Options options) { List nodes = new List(locations.Count); List tmpEdges = new List(); //Convert all the locations to nodes foreach (Location l in locations) { nodes.Add(GetNode(l)); } Route route = AStarAlgorithm.CalculateRoute(nodes, options); //TODO give route to the drawing group GlControl.DrawRoute(route); return route; } private static Boolean UntangleBrunnel(RelationshipRecord relation) { // So at this point, theres a relationship defining a brunnel (basically a shared node between lines // We don't want this, because our model requires each node to be part of ONE node, not two // So lets find all the edges in the two line features, and the node they have in common if (relation.RelationshipCatagories.Count != 3) { return false; // Won't fit the profile } List lineOne = null; List lineTwo = null; Node commonNode = null; foreach (RelationshipCat RC in relation.RelationshipCatagories) { if (RC.CatId == 3) { // False alarm, just a bridge over water (phew!) return false; // LEAVE BRITNEY ALONE } if (RC.CatId == 2) { // We got ourselves a line feature! LineFeatureRecord lfr = ParsedData.LineFeatures[RC.SectionID + RC.FeatureId.ToString()]; List lfeList = lfr.RoadParticles; List edges = new List(); foreach (LineFeatureEdge lfe in lfeList) { if (lfr.FeatCode == 4210) { // False alarm, just a railway under/over a road return false; // LEAVE BRITNEY ALONE } edges.Add(tmpEdges[lfr.SectionId + lfe.EdgeId.ToString()]); } if (lineOne == null) { lineOne = edges; } else if (lineTwo == null) { lineTwo = edges; } else { return false; // Can't be right! } } else if (RC.CatId == 1) { PointFeatureRecord lfr = ParsedData.PointFeatures[RC.SectionID + RC.FeatureId.ToString()]; if (lfr.FeatCode == 7500) { commonNode = tmpNodes[lfr.SectionId + lfr.NodesId[0].ToString()]; } else { return false; // This isnt a brunnel between two roads } } if (commonNode != null && lineOne != null && lineTwo != null) { break; // This can't be right.. (Yay for defensive programming!) } } // right now, i should have all the variables i need to untangle them. if (commonNode != null && lineOne != null && lineTwo != null) { // So in this case, we've found ourself the only situation that doesn't naturally work with our model. // This needs untanglement! Node duplicateNode = commonNode; duplicateNode.ID = -commonNode.ID; // Lets keep the commonNode for lineOne, but delete all edges that are in lineTwo foreach (Edge e in lineTwo) { commonNode.Edges.Remove(e); // We also need to replace the commonNode in the Edges in lineTwo with the duplicate if(e.FromNode.ID == commonNode.ID) { e.FromNode = duplicateNode; } else if (e.ToNode.ID == commonNode.ID) { e.ToNode = duplicateNode; } } // Remove the references between lineOne and the duplicateNode's edges foreach (Edge e in lineOne) { duplicateNode.Edges.Remove(e); } // Now we need to insert the duplicate node next to its commonNode brother foreach (Edge e in duplicateNode.Edges) { Cities[duplicateNode.PlaceName].Streets[e.RoadName].Add(e); } // AAAND that tackles THAT! return true; // Succesfully untangled } return false; // Not untangled anything. } private static Boolean UntangleBrunnelJunctions(RelationshipRecord relation) { if (relation.RelationshipCatagories.Count != 3) { return false; // Won't fit the profile } PointFeatureRecord junctionOne = null; PointFeatureRecord junctionTwo = null; PointFeatureRecord brunnel = null; foreach (RelationshipCat RC in relation.RelationshipCatagories) { if (RC.CatId == 1) { PointFeatureRecord pfr = ParsedData.PointFeatures[RC.SectionID + RC.FeatureId.ToString()]; if (pfr.FeatCode == 7500) { brunnel = pfr; } else if (pfr.FeatCode == 4120) { if (junctionOne == null) { junctionOne = pfr; } else { junctionTwo = pfr; } } } else { return false; // invalid for our cause } } if (junctionOne != null && junctionTwo != null && brunnel != null) { // So here we have it. The two junctions and the brunnel that binds them all String streetOne = null; String streetTwo = null; Node originalNode = tmpNodes[junctionOne.SectionId + junctionOne.NodesId[0].ToString()]; foreach (Edge e in originalNode.Edges) { if (streetOne == null) { streetOne = e.RoadName; } else if (streetTwo == null) { streetTwo = e.RoadName; } else { break; //Two streets found } } Node duplicateNode = new Node() { Edges = new List(originalNode.Edges), ID = -originalNode.ID, PlaceName = originalNode.PlaceName, Position = originalNode.Position, SectionID = originalNode.SectionID, Type = originalNode.Type }; // The following process makes sure that the originalNode and DuplicateNode no longer share edges foreach (Edge e in originalNode.Edges) { if (e.RoadName == streetOne) { duplicateNode.Edges.Remove(e); } } foreach (Edge e in duplicateNode.Edges) { if (e.RoadName == streetTwo) { originalNode.Edges.Remove(e); } if (e.FromNode == originalNode) { e.FromNode = duplicateNode; } else if (e.ToNode == originalNode) { e.ToNode = duplicateNode; } if(originalNode.PlaceName.Equals(String.Empty)){ foreach(Section s in Cities.Values) { if(e.Postcode.Count != 0) { if (e.RoadName == null) { e.RoadName = "Onbekende weg"; } if (s.Streets.ContainsKey(e.RoadName)) { s.Streets[e.RoadName].Add(e); // Oh, lets add it to the correct cities while we're loopin' it anyway break; } else { List tmp = new List(); tmp.Add(e); s.Streets.Add(e.RoadName, tmp); break; } } } } else{ if (e.RoadName == null) { e.RoadName = "Onbekende weg"; } if (Cities[originalNode.PlaceName].Streets.ContainsKey(e.RoadName)) { Cities[originalNode.PlaceName].Streets[e.RoadName].Add(e); } else { List x = new List(); x.Add(e); Cities[originalNode.PlaceName].Streets.Add(e.RoadName, x); } } } return true; } return false; } public static void ParseRelationships() { List postProcessing = new List(); foreach (RelationshipRecord relation in ParsedData.Relationships.Values) { if (relation.RelCode == 2200 || relation.RelCode == 1022) { postProcessing.Add(relation); } else { RelationshipCat area = null, line = null; String cityName = ""; String sectionId = relation.SectionId.ToString(); foreach (RelationshipCat cat in relation.RelationshipCatagories) { switch (cat.CatId) { case (2): line = cat; break; case (3): area = cat; break; } if (line != null && area != null) break; } if (line == null || area == null) continue; AreaFeatureRecord areaFeature = ParsedData.AreaFeatures[sectionId + area.FeatureId]; LineFeatureRecord lineFeatureRecord = ParsedData.LineFeatures[sectionId + line.FeatureId]; // check if the feature code is an area order N feature. if (areaFeature.FeatCode < 1112 || areaFeature.FeatCode > 1120) continue; if (lineFeatureRecord.FeatCode != 4110) continue; foreach (int segAttId in areaFeature.SegmentedAttributes) { SegmentedAttributeRecord segAtt = ParsedData.SegmentedAttributes[sectionId + segAttId]; foreach (SegAttributeType segAttType in segAtt.Attributes) { switch (segAttType.TypeCode) { case ("ON"): NameRecord name = ParsedData.Names[sectionId + segAttType.AttVal.Trim()]; cityName = name.Text.Trim(); break; } } } foreach (LineFeatureEdge lfe in lineFeatureRecord.RoadParticles) { Edge edge = tmpEdges[sectionId + lfe.EdgeId]; if (!Cities.ContainsKey(cityName)) { Section newSec = new Section(); if (tmpCentrum.ContainsKey(sectionId)) { newSec.CentrumNode = tmpCentrum[sectionId]; } Cities.Add(cityName, newSec); Console.WriteLine(cityName); } bool added = false; //Adding edges to the streetindexed dictionary if (edge.RoadName != null) { edge.FromNode.PlaceName = cityName; edge.ToNode.PlaceName = cityName; added = true; if (!Cities[cityName].Streets.ContainsKey(edge.RoadName)) { List edgelist = new List(); edgelist.Add(edge); Cities[cityName].Streets.Add(edge.RoadName, edgelist); } else { Cities[cityName].Streets[edge.RoadName].Add(edge); } } //Adding edges to the postcodeindexed dictionary if (edge.Postcode != null) { added = true; foreach (String s in edge.Postcode) { if (!Cities[cityName].ZipCodes.ContainsKey(s)) { List edgelist = new List(); edgelist.Add(edge); Cities[cityName].ZipCodes.Add(s, edgelist); } else { Cities[cityName].ZipCodes[s].Add(edge); } } } if (!added) { if (edge.status != 1) { Console.WriteLine(edge.EdgeID + " Has not been added " + edge.SectionID); Console.WriteLine(edge.Type + " Has not been added"); Console.WriteLine(edge.RoadName); } } } } } foreach (RelationshipRecord relation in postProcessing) { if (relation.RelCode == 2200) { Boolean unTangled = UntangleBrunnel(relation); if (!unTangled) { unTangled = UntangleBrunnelJunctions(relation); if (!unTangled) { UntangleLineBrunnel(relation); } } } else if (relation.RelCode == 1022) { Edge e = null; Node n = null; foreach (RelationshipCat rc in relation.RelationshipCatagories) { if (rc.CatId == 2) { e = tmpEdges[rc.SectionID + ParsedData.LineFeatures[rc.SectionID + rc.FeatureId.ToString()].RoadParticles[0].EdgeId.ToString()]; } else if (rc.CatId == 1) { n = tmpNodes[rc.SectionID + ParsedData.Nodes[rc.SectionID + ParsedData.PointFeatures[rc.SectionID + rc.FeatureId.ToString()].NodesId[0].ToString()].Id.ToString()]; // umad? } } if (e != null && n != null) { // e is an edge near the node // n is the node // ??? // profit } } } } private static Boolean UntangleLineBrunnel(RelationshipRecord relation) { PointFeatureRecord junction = null; PointFeatureRecord brunnel = null; LineFeatureRecord road = null; foreach (RelationshipCat RC in relation.RelationshipCatagories) { if (RC.CatId == 1) { PointFeatureRecord pfr = ParsedData.PointFeatures[RC.SectionID + RC.FeatureId.ToString()]; if (pfr.FeatCode == 7500) { brunnel = pfr; } else if (pfr.FeatCode == 4120) { if (junction == null) { junction = pfr; } } } else if (RC.CatId == 2) { LineFeatureRecord line = ParsedData.LineFeatures[RC.SectionID + RC.FeatureId.ToString()]; if (line.FeatCode == 4110) { road = line; } } else { return false; // invalid for our cause } } if (junction != null && brunnel != null && road != null) { Node originalNode = tmpNodes[junction.SectionId + junction.NodesId[0].ToString()]; Node duplicateNode = new Node() { Edges = new List(originalNode.Edges), ID = -originalNode.ID, PlaceName = originalNode.PlaceName, Position = originalNode.Position, SectionID = originalNode.SectionID, Type = originalNode.Type }; foreach (LineFeatureEdge e in road.RoadParticles) { Edge tmp = tmpEdges[road.SectionId + e.EdgeId.ToString()]; duplicateNode.Edges.Remove(tmp); } foreach (Edge e in duplicateNode.Edges) { originalNode.Edges.Remove(e); if (e.FromNode == originalNode) { e.FromNode = duplicateNode; } else if (e.ToNode == originalNode) { e.ToNode = duplicateNode; } if (e.RoadName != null) { Cities[duplicateNode.PlaceName].Streets[e.RoadName].Add(e); if (e.Postcode.Count != 0) { foreach (String s in e.Postcode) { if (Cities[duplicateNode.PlaceName].ZipCodes.ContainsKey(s)) { Cities[duplicateNode.PlaceName].ZipCodes[s].Add(e); } else { List x = new List(); x.Add(e); Cities[duplicateNode.PlaceName].ZipCodes.Add(s, x); } } } } else { if (e.Postcode.Count != 0) { foreach (String s in e.Postcode) { if (Cities[duplicateNode.PlaceName].ZipCodes.ContainsKey(s)) { Cities[duplicateNode.PlaceName].ZipCodes[s].Add(e); } else { List x = new List(); x.Add(e); Cities[duplicateNode.PlaceName].ZipCodes.Add(s, x); } } } } } } return true; } /// /// Method to cast the complex data from the parser group to the simple datamodel and link all the references /// /// Leon Koppel 12-05-11 /// public static void LinkAll() { Cities = new Dictionary(); LinkNodes(); linkEdges(); LinkAreaToSegAttr(); LinkConvertions(); ParseRelationships(); tmpNodes.Clear(); tmpEdges.Clear(); tmpCentrum.Clear(); ParsedData.ClearData(); } /// /// Cast all the nodes from the complex data and place it in a temporary dictionary /// /// Leon Koppel 12-05-11 /// private static void LinkNodes() { tmpNodes = new Dictionary(); tmpCentrum = new Dictionary(); foreach (KeyValuePair pair in ParsedData.PointFeatures) { if (pair.Value.FeatCode == 4120) { String placeName = ""; NodeType type = NodeType.Normal; foreach (int id in pair.Value.SegmentedAttributesId) { SegmentedAttributeRecord setAtt = ParsedData.SegmentedAttributes[pair.Value.SectionId + id.ToString()]; foreach (SegAttributeType attType in setAtt.Attributes) { switch (attType.TypeCode) { case ("ON"): placeName = ParsedData.Names[setAtt.SectionId + attType.AttVal.Trim()].Text; break; } } } foreach (int id in pair.Value.NodesId) { NodeRecord n = ParsedData.Nodes[pair.Value.SectionId + id.ToString()]; if (!tmpNodes.ContainsKey(n.SectionId + id.ToString())) { CoordinatesRecord coord = ParsedData.Coordinates[n.SectionId + n.XyzId.ToString()]; Node newNode = new Node(); newNode.Type = type; newNode.PlaceName = placeName; newNode.Position = coord.Coords[0]; newNode.SectionID = n.SectionId; tmpNodes.Add(n.SectionId + id.ToString(), newNode); } } } else { NodeRecord n = ParsedData.Nodes[pair.Value.SectionId + pair.Value.NodesId[0].ToString()]; CoordinatesRecord coord = ParsedData.Coordinates[n.SectionId + n.XyzId.ToString()]; POI poi = new POI(); switch (pair.Value.FeatCode) { case (7360): //Camping poi.Type = POIType.CampingGround; listCampingGround.Add(poi); break; case (9927): //Dierentuin poi.Type = POIType.Zoo; listZoo.Add(poi); break; case (7314): //Hotel poi.Type = POIType.Hotel; listHotel.Add(poi); break; case (7317): //Museum poi.Type = POIType.Museum; listMuseum.Add(poi); break; case (7313): //ParkeerGarage poi.Type = POIType.ParkingGarage; listParkingGarage.Add(poi); break; case (7322): //Politie poi.Type = POIType.PoliceStation; listPoliceStation.Add(poi); break; case (7324): //Post poi.Type = POIType.PostOffice; listPostOffice.Add(poi); break; case (7315): //Restaurant poi.Type = POIType.Restaurant; listRestaurant.Add(poi); break; case (7372): //School poi.Type = POIType.School; listSchool.Add(poi); break; case (7380): //Station poi.Type = POIType.RailwayStation; listRailwayStation.Add(poi); break; case (7311): //Tankstation poi.Type = POIType.PetrolStation; listPetrolStation.Add(poi); break; case (7318): //Theater poi.Type = POIType.Theatre; listTheatre.Add(poi); break; case (7376): //ToeristenAttractie poi.Type = POIType.ImportantTouristAttraction; listImportantTouristAttraction.Add(poi); break; case (7337): //Uitzichtspunt poi.Type = POIType.PanoramicView; listPanoramicView.Add(poi); break; case (7316): //VVV poi.Type = POIType.TouristInformationOffice; listTouristInformationOffice.Add(poi); break; case (7321): // Ziekenhuis poi.Type = POIType.Hospital; listHospital.Add(poi); break; case (7379): // Centrum if (!tmpCentrum.ContainsKey(n.SectionId.ToString())) { Node newNode = new Node(); newNode.Position = coord.Coords[0]; tmpCentrum.Add(n.SectionId.ToString(), newNode); } break; default: poi.Type = POIType.Undefined; break; } if (poi.Type != POIType.Undefined) { poi.Position = coord.Coords[0]; } } } foreach (KeyValuePair nr in ParsedData.Nodes) { if (!tmpNodes.ContainsKey(nr.Value.SectionId + nr.Value.Id.ToString())) { Node n = new Node(); n.ID = nr.Value.Id; n.Position = ParsedData.Coordinates[nr.Value.SectionId + nr.Value.XyzId.ToString()].Coords[0]; n.SectionID = nr.Value.SectionId; tmpNodes.Add(nr.Value.SectionId + nr.Value.Id.ToString(), n); if (tmpCentrum.ContainsKey(n.SectionID.ToString())) { if (tmpCentrum[n.SectionID.ToString()].Position == n.Position) { tmpCentrum[n.SectionID.ToString()] = n; } } } } } // // Link a Area to a segmentedAttribute // // Wim Eikelboom 16-5-2011 // private static void LinkAreaToSegAttr() { foreach (KeyValuePair area in ParsedData.AreaFeatures) { AreaType type = new AreaType(); String name = ""; List positions = new List(); if (area.Value.FeatCode == 4310) { type = AreaType.WaterElement; } else if ((area.Value.FeatCode == 7170) || (area.Value.FeatCode == 7120)) { type = AreaType.ParkElement; } else if ((area.Value.FeatCode == 9715) || (area.Value.FeatCode == 9720)) { type = AreaType.IndustrialElement; } else if (area.Value.FeatCode == 3110) { type = AreaType.UrbanElement; } else continue; foreach (int segAttrId in area.Value.SegmentedAttributes) { SegmentedAttributeRecord segAttr = ParsedData.SegmentedAttributes[area.Value.SectionId + segAttrId.ToString()]; foreach (SegAttributeType attType in segAttr.Attributes) { switch (attType.TypeCode) { case ("ON"): name = ParsedData.Names[segAttr.SectionId + attType.AttVal.Trim()].Text; break; } } foreach (int face in area.Value.FaceId) { Area a = new Area(); FaceRecord fr = ParsedData.Faces[area.Value.SectionId + face.ToString()]; foreach (FaceEdge faceEdge in fr.Edges) { EdgeRecord er = ParsedData.Edges[area.Value.SectionId + faceEdge.EdgeId.ToString()]; NodeRecord fromNode = ParsedData.Nodes[er.SectionId + er.FNodeId.ToString()]; NodeRecord toNode = ParsedData.Nodes[er.SectionId + er.TNodeId.ToString()]; CoordinatesRecord fNCoord = ParsedData.Coordinates[er.SectionId + fromNode.XyzId.ToString()]; CoordinatesRecord tNCoord = ParsedData.Coordinates[er.SectionId + toNode.XyzId.ToString()]; CoordinatesRecord coord = null; if (er.XyzId != -1) coord = ParsedData.Coordinates[er.SectionId + er.XyzId.ToString()]; if (faceEdge.Orientation == 0) { // from fromNode to toNode a.Positions.Add(fNCoord.Coords[0]); if (coord != null) { foreach (Point p in coord.Coords) a.Positions.Add(p); } } else { // from toNode to fromNode a.Positions.Add(tNCoord.Coords[0]); if (coord != null) { for (int i = coord.Coords.Count - 1; i >= 0; i--) { a.Positions.Add(coord.Coords[i]); } } } } a.Name = name; a.Type = type; listArea.Add(a); } } } } /// /// Method to get a node from a location, /// /// Location /// Node public static Node GetNode(Location l) { List edges = new List(); Node houseNode = new Node(); if (!string.IsNullOrEmpty(l.ZipCode)) { edges = Cities[l.City].ZipCodes[l.ZipCode]; } else if (!string.IsNullOrEmpty(l.Street)) { edges = Cities[l.City].Streets[l.Street]; } if (string.IsNullOrEmpty(l.Housenumber)) { if (edges.Count != 0) { houseNode = edges[0].ToNode; } else if(!string.IsNullOrEmpty(l.City)) { houseNode = Cities[l.City].Streets.Values.ElementAt(0).ElementAt(0).FromNode; } return houseNode; } else { int numericHousenumber = SplitHouseNumber(l.Housenumber); bool found = false; bool even = (numericHousenumber % 2 == 0) ? true : false; bool left = false; foreach (Edge e in edges) { //1 No House Numbers at All if (e.HousenumbersTotal == TotalHousenumberStructure.None) { continue; } int maxHousenumberLeft = -1; int minHousenumberLeft = -1; int maxHousenumberRight = -1; int minHousenumberRight = -1; if (e.HousenumbersLeft != HousenumberStructure.None) { int h1 = SplitHouseNumber(e.FirstHouseNumberLeft); int h2 = SplitHouseNumber(e.LastHouseNumberLeft); maxHousenumberLeft = (h1 > h2) ? h1 : h2; minHousenumberLeft = (h1 < h2) ? h1 : h2; } if (e.HousenumbersRight != HousenumberStructure.None) { int h1 = SplitHouseNumber(e.FirstHouseNumberRight); int h2 = SplitHouseNumber(e.LastHouseNumberRight); maxHousenumberRight = (h1 > h2) ? h1 : h2; minHousenumberRight = (h1 < h2) ? h1 : h2; } //2 Regular with Odd & Even Numbers at Both Sides if (e.HousenumbersTotal == TotalHousenumberStructure.Both) { if (minHousenumberLeft <= numericHousenumber && numericHousenumber <= maxHousenumberLeft) { found = true; left = true; } else if (minHousenumberRight <= numericHousenumber && numericHousenumber <= maxHousenumberRight) { found = true; } } //3 Regular with Odd & Even Numbers at Different Sides else if (e.HousenumbersTotal == TotalHousenumberStructure.Different) { if (even) { if (e.HousenumbersLeft == HousenumberStructure.Even) { if (minHousenumberLeft <= numericHousenumber && numericHousenumber <= maxHousenumberLeft) { found = true; left = true; } } else if (e.HousenumbersRight == HousenumberStructure.Even) { if (minHousenumberRight <= numericHousenumber && numericHousenumber <= maxHousenumberRight) { found = true; } } } //if housenumer is odd else { if (e.HousenumbersLeft == HousenumberStructure.Odd) { if (minHousenumberLeft <= numericHousenumber && numericHousenumber <= maxHousenumberLeft) { found = true; left = true; } } else if (e.HousenumbersRight == HousenumberStructure.Odd) { if (minHousenumberRight <= numericHousenumber && numericHousenumber <= maxHousenumberRight) { found = true; } } } } //4 Irregular House Number Structure else if (e.HousenumbersTotal == TotalHousenumberStructure.Irregular) { //Left side if (e.HousenumbersLeft == HousenumberStructure.Irregular) { if (minHousenumberLeft <= numericHousenumber && numericHousenumber <= maxHousenumberLeft) { found = true; left = true; } } else if (e.HousenumbersLeft == HousenumberStructure.Even) { if (even) { if (minHousenumberLeft <= numericHousenumber && numericHousenumber <= maxHousenumberLeft) { found = true; left = true; } } } else if (e.HousenumbersLeft == HousenumberStructure.Odd) { if (!even) { if (minHousenumberLeft <= numericHousenumber && numericHousenumber <= maxHousenumberLeft) { found = true; left = true; } } } //Right side else if (e.HousenumbersRight == HousenumberStructure.Irregular) { if (minHousenumberRight <= numericHousenumber && numericHousenumber <= maxHousenumberRight) { found = true; } } else if (e.HousenumbersRight == HousenumberStructure.Even) { if (even) { if (minHousenumberRight <= numericHousenumber && numericHousenumber <= maxHousenumberRight) { found = true; } } } else if (e.HousenumbersRight == HousenumberStructure.Odd) { if (!even) { if (minHousenumberRight <= numericHousenumber && numericHousenumber <= maxHousenumberRight) { found = true; } } } } if (found) { return e.ToNode; //calculate percentage factor on the edge float factor; if (left) { factor = maxHousenumberLeft - minHousenumberLeft; factor = factor / maxHousenumberLeft; } else { factor = maxHousenumberRight - minHousenumberRight; factor = factor / maxHousenumberRight; } //if the factor is 1.0 (100%) return the highest node if (factor == 1.0) { if (left) { houseNode = (maxHousenumberLeft == SplitHouseNumber(e.LastHouseNumberLeft)) ? e.FromNode : e.ToNode; } else { houseNode = (maxHousenumberRight == SplitHouseNumber(e.LastHouseNumberRight)) ? e.FromNode : e.ToNode; } return houseNode; } //if the factor is 1.0 (100%) return the lowest node if (factor == 0.0) { if (left) { houseNode = (maxHousenumberLeft == SplitHouseNumber(e.FirstHouseNumberLeft)) ? e.FromNode : e.ToNode; } else { houseNode = (maxHousenumberRight == SplitHouseNumber(e.FirstHouseNumberRight)) ? e.FromNode : e.ToNode; } return houseNode; } //Calculate distance from a to p float edgeLength = e.GetLength(); int distAP = (int)(edgeLength * factor); //if the founded edge has no positions if (e.Positions == null || e.Positions.Count == 0) { float deltaX = e.ToNode.Position.X - e.FromNode.Position.X; float deltaY = e.ToNode.Position.Y - e.FromNode.Position.Y; float distAB = edgeLength; float deltaXAP = (deltaX * distAP) / distAB; float deltaYAP = (deltaY * distAP) / distAB; Point p = new Point(); p.X = (int)(e.FromNode.Position.X + deltaXAP); p.Y = (int)(e.ToNode.Position.Y + deltaYAP); houseNode.Position = p; houseNode.ID = -1; Edge edgeAP = new Edge(); edgeAP.EdgeID = -1; edgeAP.FromNode = houseNode; edgeAP.ToNode = e.ToNode; edgeAP.MaxSpeed = e.MaxSpeed; edgeAP.Bidirectional = e.Bidirectional; edgeAP.UsableByBike = e.UsableByBike; edgeAP.UsableByCar = e.UsableByCar; edgeAP.UsableByFoot = e.UsableByFoot; Edge edgePB = new Edge(); edgePB.EdgeID = -1; edgePB.FromNode = e.FromNode; edgePB.ToNode = houseNode; edgePB.MaxSpeed = e.MaxSpeed; edgePB.Bidirectional = e.Bidirectional; edgePB.UsableByBike = e.UsableByBike; edgePB.UsableByCar = e.UsableByCar; edgePB.UsableByFoot = e.UsableByFoot; houseNode.Edges.Add(edgeAP); houseNode.Edges.Add(edgePB); e.ToNode.Edges.Add(edgeAP); e.FromNode.Edges.Add(edgePB); return houseNode; } //Calculate the position on the edge float length = 0; for (int i = 0; i < e.Positions.Count + 1; i++) { Point a = (i == 0) ? e.FromNode.Position : e.Positions[i - 1]; Point b = (i == e.Positions.Count) ? e.ToNode.Position : e.Positions[i]; Point c = new Point(b.X, a.Y); float xd = c.X - a.X; float yd = b.Y - c.Y; length += (float)Math.Sqrt(xd * xd + yd * yd); if (length >= distAP) { float deltaX = a.X - b.X; float deltaY = a.Y - b.Y; c = new Point(b.X, a.Y); xd = c.X - a.X; yd = b.Y - c.Y; float distAB = (int)Math.Sqrt(xd * xd + yd * yd); float newDistAP = (int)(distAP - length); float deltaXAP = (deltaX * newDistAP) / distAB; float deltaYAP = (deltaY * newDistAP) / distAB; Point p = new Point(); p.X = (int)(a.X + deltaXAP); p.Y = (int)(b.Y + deltaYAP); houseNode.Position = p; houseNode.ID = -1; Edge edgeAP = new Edge(); edgeAP.EdgeID = -1; edgeAP.FromNode = houseNode; edgeAP.ToNode = e.ToNode; edgeAP.MaxSpeed = e.MaxSpeed; edgeAP.Bidirectional = e.Bidirectional; edgeAP.UsableByBike = e.UsableByBike; edgeAP.UsableByCar = e.UsableByCar; edgeAP.UsableByFoot = e.UsableByFoot; Edge edgePB = new Edge(); edgePB.EdgeID = -1; edgePB.FromNode = e.FromNode; edgePB.ToNode = houseNode; edgePB.MaxSpeed = e.MaxSpeed; edgePB.Bidirectional = e.Bidirectional; edgePB.UsableByBike = e.UsableByBike; edgePB.UsableByCar = e.UsableByCar; edgePB.UsableByFoot = e.UsableByFoot; for (int u = 1; u < i; u++) { edgeAP.Positions.Add(e.Positions[u]); edgePB.Positions.Add(e.Positions[e.Positions.Count - u]); } houseNode.Edges.Add(edgeAP); houseNode.Edges.Add(edgePB); e.ToNode.Edges.Add(edgeAP); e.FromNode.Edges.Add(edgePB); return houseNode; } } } } } throw new Exception("Housenumber not found"); } /// /// Returns a housnumber in a short instead of a string /// /// /// public static short SplitHouseNumber(string houseNumber) { if (houseNumber == null) { LogException.Log("SplitHouseNumber", new Exception("Empty housenumber")); return 0; } String tmp = string.Empty; char[] c = houseNumber.ToCharArray(); for (int i = 0; i < c.Length; i++) { if (Char.IsNumber(c[i])) { tmp += c[i]; } else { break; } } return Int16.Parse(tmp); } /// /// Grabs all edge information from the Parser objects, and stuffs this into a temporary dictionary called edges for use in later linking with nodes. /// private static void linkEdges() { tmpEdges = new Dictionary(); foreach (LineFeatureRecord lfr in ParsedData.LineFeatures.Values) { if (lfr.FeatCode == 4110) { string roadName = null; bool isRail = false; LineType type = LineType.UnspecifiedElement; int maxSpeed = 0; string postcode = null; TotalHousenumberStructure houseNStructure = TotalHousenumberStructure.None; HousenumberStructure houseRStructure = HousenumberStructure.None; HousenumberStructure houseLStructure = HousenumberStructure.None; string firstHouseNumberRight = null; string lastHouseNumberRight = null; string firstHouseNumberLeft = null; string lastHouseNumberLeft = null; int directionality = -1; List routeNumbers = new List(); List postalCodes = new List(); int accesstype = -1; foreach (int i in lfr.SegmentedAttributes) { SegmentedAttributeRecord sar = ParsedData.SegmentedAttributes[lfr.SectionId + i.ToString()]; foreach (SegAttributeType sat in sar.Attributes) { if (sat.TypeCode.Equals("ON")) { roadName = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text.Trim(); } else if (sat.TypeCode.Equals("FW")) { if (sat.AttVal.Trim() == "14" || sat.AttVal.Trim() == "15") { accesstype = 2; } else if (sat.AttVal.Trim() == "4") { roadName = "Rotonde " + roadName; accesstype = 0; } else { accesstype = 0; } } else if (sat.TypeCode.Equals("3A")) { type = LineType.RailElement; isRail = true; } else if (sat.TypeCode.Equals("SP")) { maxSpeed = int.Parse(sat.AttVal); if (maxSpeed >= 100) { accesstype = 5; } else if (accesstype != 0 || accesstype != 3) { accesstype = 0; } } else if (sat.TypeCode.Equals("RN")) { routeNumbers.Add(ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text.Trim()); } else if (sat.TypeCode.Equals("FC") && !isRail) { int intType = int.Parse(sat.AttVal); type = (LineType)intType; } else if (sat.TypeCode.Equals("5S")) { postcode = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text.Trim(); } else if (sat.TypeCode.Equals("5M")) { if (postcode == null || postcode.Trim() == String.Empty) { postcode = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text.Trim(); } } else if (sat.TypeCode.Equals("HS")) { int intHouseStruct = int.Parse(sat.AttVal); intHouseStruct--; houseNStructure = (TotalHousenumberStructure)intHouseStruct; } else if (sat.TypeCode.Equals("4L")) { int intHouseStruct = int.Parse(sat.AttVal); intHouseStruct--; houseLStructure = (HousenumberStructure)intHouseStruct; } else if (sat.TypeCode.Equals("4R")) { int intHouseStruct = int.Parse(sat.AttVal); intHouseStruct--; houseRStructure = (HousenumberStructure)intHouseStruct; } else if (sat.TypeCode.Equals("RS")) { firstHouseNumberRight = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text; } else if (sat.TypeCode.Equals("RE")) { lastHouseNumberRight = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text; } else if (sat.TypeCode.Equals("LS")) { firstHouseNumberLeft = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text; } else if (sat.TypeCode.Equals("LE")) { lastHouseNumberLeft = ParsedData.Names[lfr.SectionId + sat.AttVal.Trim()].Text; } else if (sat.TypeCode.Equals("VT")) { if (sat.AttVal.Trim() == "24") { if (accesstype == 0) { accesstype = 3; } else if (accesstype == 2) { accesstype = 4; } else { accesstype = 2; } } } else if (sat.TypeCode.Equals("SR")) { if (sat.AttVal.Trim() == "2") { accesstype = -2; } } else if (sat.TypeCode.Equals("2T")) { if (sat.AttVal.Trim() == "1") { accesstype = -2; } } else if (sat.TypeCode.Equals("DF")) { directionality = int.Parse(sat.AttVal.Trim()); } if (!string.IsNullOrEmpty(postcode)) { postalCodes.Add(postcode); } } } foreach (LineFeatureEdge lfe in lfr.RoadParticles) { Edge e; if (!tmpEdges.ContainsKey(lfr.SectionId + lfe.EdgeId.ToString())) { e = new Edge(); tmpEdges.Add(lfr.SectionId + lfe.EdgeId.ToString(), e); } else { e = tmpEdges[lfr.SectionId + lfe.EdgeId.ToString()]; } e.EdgeID = lfe.EdgeId; e.Type = type; e.FirstHouseNumberLeft = firstHouseNumberLeft; e.FirstHouseNumberRight = firstHouseNumberRight; e.LastHouseNumberLeft = lastHouseNumberLeft; e.LastHouseNumberRight = lastHouseNumberRight; e.HousenumbersTotal = houseNStructure; e.HousenumbersLeft = houseLStructure; e.HousenumbersRight = houseRStructure; e.MaxSpeed = maxSpeed; e.Postcode.AddRange(postalCodes); e.Routenumbers.AddRange(routeNumbers); if (accesstype == 0) { e.UsableByCar = true; e.UsableByFoot = true; e.UsableByBike = true; } else if (accesstype == 3) { e.UsableByCar = true; e.UsableByBike = true; } else if (accesstype == 4) { e.UsableByFoot = true; e.UsableByBike = true; } else if (accesstype == 5) { e.UsableByCar = true; } else if (accesstype == 2) { e.UsableByFoot = true; } else if (accesstype == 1) { e.UsableByBike = true; } else if (accesstype == -2) { // NONE SHALL PASS e.UsableByBike = false; e.UsableByFoot = false; e.UsableByCar = false; } if (roadName != null && !roadName.Equals(String.Empty)) { e.RoadName = roadName; } else { foreach (String s in routeNumbers) { e.RoadName += "(" + s + ")"; } } if (directionality == 1) { e.Bidirectional = 0; } else if (directionality == 2) { e.Bidirectional = 1; } else if (directionality == 3) { e.Bidirectional = 2; } else if (directionality == 4) { e.Bidirectional = 3; } e.SectionID = lfr.SectionId; EdgeRecord er; ParsedData.Edges.TryGetValue(lfr.SectionId + lfe.EdgeId.ToString(), out er); if (er != null) { e.FromNode = tmpNodes[lfr.SectionId + er.FNodeId.ToString()]; e.FromNode.Edges.Add(e); e.ToNode = tmpNodes[lfr.SectionId + er.TNodeId.ToString()]; e.ToNode.Edges.Add(e); e.status = er.Status; if (er.XyzId != -1) { e.Positions = ParsedData.Coordinates[lfr.SectionId + er.XyzId.ToString()].Coords; } } else { LogException.Log("LinkEdges", new Exception("Edge record not found" + lfr.SectionId + lfe.EdgeId)); } } } } } private static void LinkConvertions() { foreach (ConversionRecord conversion in ParsedData.Conversions) { int sectionIntern = conversion.SectionInt; int sectionExtern = conversion.SectionExt; int featCodeIntern = conversion.FeatInt; int featCodeExtern = conversion.FeatExt; int idIntern = conversion.IntId; int idExtern = conversion.ExtId; if (featCodeExtern != featCodeIntern) continue; switch (featCodeIntern) { // point feature case (1): String internKey = sectionIntern + idIntern.ToString(); String externKey = sectionExtern + idExtern.ToString(); if (!ParsedData.PointFeatures.ContainsKey(internKey)) continue; if (!ParsedData.PointFeatures.ContainsKey(externKey)) continue; PointFeatureRecord pFint = ParsedData.PointFeatures[internKey]; PointFeatureRecord pFext = ParsedData.PointFeatures[externKey]; for (int i = 0; i < pFint.NodesId.Count; i++) { Node nodeIntern = tmpNodes[sectionIntern + pFint.NodesId[i].ToString()]; Node nodeExtern = tmpNodes[sectionExtern + pFext.NodesId[i].ToString()]; for (int j = 0; j < nodeExtern.Edges.Count; j++) { Edge edge = nodeExtern.Edges[j]; nodeIntern.Edges.Add(edge); if (edge.FromNode == nodeExtern) edge.FromNode = nodeIntern; else if(edge.ToNode == nodeExtern) edge.ToNode = nodeIntern; } } break; } } } #endregion } }