rendered paste bodyusing 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
/// <summary>
/// Dictionary of sections called cities
/// </summary>
public static Dictionary<string, Section> Cities { get; set; }
/// <summary>
/// Temporary dictionary of edges for use in linking
/// </summary>
private static Dictionary<string, Edge> tmpEdges;
/// <summary>
/// Temporary dictionary of nodes for use in linking
/// </summary>
private static Dictionary<string, Node> tmpNodes;
/// <summary>
/// Temporary dictionary for the centrum points
/// </summary>
private static Dictionary<string, Node> tmpCentrum;
/// <summary>
/// List with all areas which can be used for drawing areas
/// </summary>
public static List<Area> listArea = new List<Area>();
/// <summary>
/// List of Points of Interest
/// </summary>
public static List<POI> listPetrolStation = new List<POI>();
public static List<POI> listParkingGarage = new List<POI>();
public static List<POI> listHotel = new List<POI>();
public static List<POI> listRestaurant = new List<POI>();
public static List<POI> listTouristInformationOffice = new List<POI>();
public static List<POI> listMuseum = new List<POI>();
public static List<POI> listTheatre = new List<POI>();
public static List<POI> listHospital = new List<POI>();
public static List<POI> listPoliceStation = new List<POI>();
public static List<POI> listPostOffice = new List<POI>();
public static List<POI> listZoo = new List<POI>();
public static List<POI> listPanoramicView = new List<POI>();
public static List<POI> listCampingGround = new List<POI>();
public static List<POI> listSchool = new List<POI>();
public static List<POI> listImportantTouristAttraction = new List<POI>();
public static List<POI> listRailwayStation = new List<POI>();
#endregion
#region Methods of Location
/// <summary>
/// Navigate from 1 location to another with the shortest path available.
///
/// Leon Koppel 17-05-11
/// </summary>
public static Route Navigate(List<Location> locations, Options options)
{
List<Node> nodes = new List<Node>(locations.Count);
List <Edge> tmpEdges = new List<Edge>();
//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<Edge> lineOne = null;
List<Edge> 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<LineFeatureEdge> lfeList = lfr.RoadParticles;
List<Edge> edges = new List<Edge>();
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<Edge>(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<Edge> tmp = new List<Edge>();
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<Edge> x = new List<Edge>();
x.Add(e);
Cities[originalNode.PlaceName].Streets.Add(e.RoadName, x);
}
}
}
return true;
}
return false;
}
public static void ParseRelationships()
{
List<RelationshipRecord> postProcessing = new List<RelationshipRecord>();
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<Edge> edgelist = new List<Edge>();
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<Edge> edgelist = new List<Edge>();
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<Edge>(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<Edge> x = new List<Edge>();
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<Edge> x = new List<Edge>();
x.Add(e);
Cities[duplicateNode.PlaceName].ZipCodes.Add(s, x);
}
}
}
}
}
}
return true;
}
/// <summary>
/// Method to cast the complex data from the parser group to the simple datamodel and link all the references
///
/// Leon Koppel 12-05-11
/// </summary>
public static void LinkAll()
{
Cities = new Dictionary<string, Section>();
LinkNodes();
linkEdges();
LinkAreaToSegAttr();
LinkConvertions();
ParseRelationships();
tmpNodes.Clear();
tmpEdges.Clear();
tmpCentrum.Clear();
ParsedData.ClearData();
}
/// <summary>
/// Cast all the nodes from the complex data and place it in a temporary dictionary
///
/// Leon Koppel 12-05-11
/// </summary>
private static void LinkNodes()
{
tmpNodes = new Dictionary<string, Node>();
tmpCentrum = new Dictionary<string, Node>();
foreach (KeyValuePair<string, PointFeatureRecord> 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<string, NodeRecord> 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;
}
}
}
}
}
// <summary>
// Link a Area to a segmentedAttribute
//
// Wim Eikelboom 16-5-2011
// </summary>
private static void LinkAreaToSegAttr()
{
foreach (KeyValuePair<string, AreaFeatureRecord> area in ParsedData.AreaFeatures)
{
AreaType type = new AreaType();
String name = "";
List<Point> positions = new List<Point>();
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);
}
}
}
}
/// <summary>
/// Method to get a node from a location,
/// </summary>
/// <param name="l">Location</param>
/// <returns>Node</returns>
public static Node GetNode(Location l)
{
List<Edge> edges = new List<Edge>();
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");
}
/// <summary>
/// Returns a housnumber in a short instead of a string
/// </summary>
/// <param name="houseNumber"></param>
/// <returns></returns>
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);
}
/// <summary>
/// Grabs all edge information from the Parser objects, and stuffs this into a temporary dictionary called edges for use in later linking with nodes.
/// </summary>
private static void linkEdges()
{
tmpEdges = new Dictionary<string, Edge>();
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<String> routeNumbers = new List<String>();
List<String> postalCodes = new List<string>();
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
}
}