/// <summary> /// Gets the coordinates from specified district key. /// </summary> /// <returns>The coordinates. Multiple group of coordinates separated by top level array element.</returns> /// <param name="districtKey">District key as country-district-...</param> public static IEnumerable<IEnumerable<Coordinate>> GetCoordinates(String districtKey) { var geo = new List<IEnumerable<Coordinate>>(); if (districtKey == null) return null; var level = 0; var distictKeys = districtKey.Split('-'); if (districtKey != null) level = districtKey.Split('-').Length - 1; var rootKey = distictKeys[0]; if (!shapeFileInfoLookup.ContainsKey(rootKey)) throw new KeyNotFoundException("Key = " + rootKey + " not found from configuration."); var levelMap = shapeFileInfoLookup[rootKey].ShapeFileMaps.FirstOrDefault(m => m.Level == level); if (levelMap == null) { throw new KeyNotFoundException( "No ShapeFile entry for Level = " + level + " computed from: " + districtKey); } var rootPath = shapeFileInfoLookup[rootKey].ShapeFilesRootPath; var fileName = shapeFileInfoLookup[rootKey].ShapeFileMaps[level].FileName; var filePath = rootPath + fileName; var cachePath = coordCachePath; if (HttpContext.Current != null) { filePath = HttpContext.Current.Server.MapPath(filePath); if(cachePath != null) cachePath = HttpContext.Current.Server.MapPath(cachePath + "/" + districtKey); } // Get coordinate from cache instead if found. if (cachePath != null && File.Exists(cachePath)) { try { using (var streamReader = File.OpenText(cachePath)) { String s = streamReader.ReadToEnd(); var coordinates = s.Split('|').Select( ss => { var areas = ss.Split('-').Select( ax => { var p = ax.Split(','); return new Coordinate { X = Double.Parse(p[0]), Y = Double.Parse(p[1]) }; }); return areas; }); if (coordinates.Any(Enumerable.Any)) geo.AddRange(coordinates); } return geo; } catch(Exception ex) { //TODO: Log this exception. Console.WriteLine(ex.Message); } } var factory = new GeometryFactory(); using (var shapeFileDataReader = new ShapefileDataReader(filePath, factory)) { var shapeHeader = shapeFileDataReader.ShapeHeader; var bounds = shapeHeader.Bounds; var header = shapeFileDataReader.DbaseHeader; shapeFileDataReader.Reset(); while (shapeFileDataReader.Read()) { var keys = new string[header.NumFields]; var geometry = shapeFileDataReader.Geometry; var shapeDisticts = new List<String>(); for (var i = 0; i < header.NumFields; i++) { var fieldDescriptor = header.Fields[i]; keys[i] = fieldDescriptor.Name; var fieldValue = shapeFileDataReader.GetValue(i) + ""; for (var j = 0; j <= level; j++) { if (fieldDescriptor.Name == "NAME_" + j) { shapeDisticts.Add(fieldValue.ToLower()); } } } var shapeDistictKey = String.Join("-", shapeDisticts.ToArray()); Console.WriteLine(shapeDistictKey); if (districtKey == shapeDistictKey) { // Find the duplicate coordinates. It is the polygon loop. var endPointLookup = geometry.Coordinates. GroupBy(k => k.X + "," + k.Y). Where(g => g.Count() >= 2). ToLookup(g => g.Key, null); String endPoint = null; var coords = new List<Coordinate>(); try { for (long i = 0; i < geometry.Coordinates.LongLength; i++) { if(geometry.Coordinates[i] == null) continue; var key = geometry.Coordinates[i].X + "," + geometry.Coordinates[i].Y; coords.Add(geometry.Coordinates[i]); if (endPoint == null) { if (endPointLookup.Contains(key)) endPoint = key; } else { if (endPoint == key) { endPoint = null; geo.Add(coords); coords = new List<Coordinate>(); } } } } catch(Exception ex) { Console.WriteLine(ex.Message); throw; } break; } } shapeFileDataReader.Close(); shapeFileDataReader.Dispose(); } // Build cache. if (cachePath != null) { var physicalCachePath = coordCachePath; if (HttpContext.Current != null) physicalCachePath = HttpContext.Current.Server.MapPath(physicalCachePath); if (!Directory.Exists(physicalCachePath)) Directory.CreateDirectory(physicalCachePath); var sb = new StringBuilder(); foreach (var coords in geo) { foreach (var coord in coords) { sb.AppendFormat("{0},{1}", coord.X, coord.Y); sb.Append("-"); } if(sb.Length > 0) sb.Remove(sb.Length - 1, 1); sb.Append("|"); } if(sb.Length > 0) sb.Remove(sb.Length - 1, 1); var coordCache = sb.ToString(); File.WriteAllText(cachePath, coordCache); } return geo; }
public bool ImportShapes(List<string> files, bool latlon, bool useShapeProps, bool useElev, bool elevFeet) { GeometryFactory factory; ShapefileDataReader shapeFileDataReader; ArrayList features; Feature feature; AttributesTable attributesTable; string[] keys; Geometry geometry; DbaseFieldDescriptor fldDescriptor; int polyCount = (int)dal.GetPolyCount(); GpsPoint gps; int index = 0; _Polygons = new Dictionary<string, TtPolygon>(); _Points = new List<TtPoint>(); List<TtPoint> tmpPoints = new List<TtPoint>(); try { foreach (string file in files) { //polyCount = 1; factory = new GeometryFactory(); shapeFileDataReader = new ShapefileDataReader(file, factory); DbaseFileHeader header = shapeFileDataReader.DbaseHeader; features = new ArrayList(); while (shapeFileDataReader.Read()) { feature = new Feature(); attributesTable = new AttributesTable(); keys = new string[header.NumFields]; geometry = (Geometry)shapeFileDataReader.Geometry; for (int i = 0; i < header.NumFields; i++) { fldDescriptor = header.Fields[i]; keys[i] = fldDescriptor.Name; attributesTable.AddAttribute(fldDescriptor.Name, shapeFileDataReader.GetValue(i)); } feature.Geometry = geometry; feature.Attributes = attributesTable; features.Add(feature); } bool areAllPoints = true; foreach (Feature feat in features) { if (feat.Geometry.GeometryType.ToLower() != "point") { areAllPoints = false; break; } } //if all features are points if (areAllPoints) { tmpPoints.Clear(); _Poly = new TtPolygon(1000 * polyCount + 10); _Poly.Name = Path.GetFileNameWithoutExtension(file); index = 0; foreach (Feature feat in features) { //if features is only a point there should only be 1 coord foreach (Coordinate coord in feat.Geometry.Coordinates) { gps = new GpsPoint(); gps.OnBnd = true; gps.Index = index; index++; gps.MetaDefCN = _Meta.CN; if (tmpPoints.Count > 0) gps.PID = PointNaming.NamePoint(tmpPoints.Last(), _Poly); else gps.PID = PointNaming.NameFirstPoint(_Poly); if (latlon) { double x,y; TtUtils.LatLontoUTM(coord.Y, coord.X, _Meta.Zone, out y, out x); gps.UnAdjX = x; gps.UnAdjY = y; } else { gps.UnAdjX = coord.X; gps.UnAdjY = coord.Y; } if (useElev) { if (coord.Z != double.NaN) { if (elevFeet) gps.UnAdjZ = TtUtils.ConvertToMeters(coord.Z, Unit.FEET_TENTH); else gps.UnAdjZ = coord.Z; } else gps.UnAdjZ = 0; } else gps.UnAdjZ = 0; gps.PolyCN = _Poly.CN; gps.PolyName = _Poly.Name; gps.GroupCN = Values.MainGroup.CN; gps.GroupName = Values.MainGroup.Name; tmpPoints.Add(gps); } _Points.AddRange(tmpPoints); } _Polygons.Add(_Poly.CN, _Poly); polyCount++; } else //else get points out of each features { int fidInc = 0; foreach (Feature feat in features) { tmpPoints.Clear(); _Poly = new TtPolygon(1000 * polyCount + 10); if (features.Count < 2) _Poly.Name = Path.GetFileNameWithoutExtension(file); else _Poly.Name = String.Format("{0}-{1}", fidInc++, Path.GetFileNameWithoutExtension(file)); #region Shape Desc Properties if (useShapeProps) { object[] objs = feat.Attributes.GetValues(); string[] names = feat.Attributes.GetNames(); string objv; for (int i = 0; i < feat.Attributes.Count; i++) { if (objs[i] is string) { objv = (string)objs[i]; if (objv.IsEmpty()) continue; switch (names[i].ToLower()) { case "description": case "comment": case "poly": if (_Poly.Description.IsEmpty()) _Poly.Description = objv; else _Poly.Description = String.Format("{0} | {1}", _Poly.Description, objv); break; case "name": case "unit": _Poly.Name = objv; break; } } } } #endregion index = 0; foreach (Coordinate coord in feat.Geometry.Coordinates) { gps = new GpsPoint(); gps.OnBnd = true; gps.Index = index; index++; gps.MetaDefCN = _Meta.CN; if (tmpPoints.Count > 0) gps.PID = PointNaming.NamePoint(tmpPoints.Last(), _Poly); else gps.PID = PointNaming.NameFirstPoint(_Poly); if (latlon) { double x, y; TtUtils.LatLontoUTM(coord.Y, coord.X, _Meta.Zone, out y, out x); gps.UnAdjX = x; gps.UnAdjY = y; } else { gps.UnAdjX = coord.X; gps.UnAdjY = coord.Y; } if (useElev) { if (coord.Z == double.NaN) { if (elevFeet) gps.UnAdjZ = TtUtils.ConvertToMeters(coord.Z, Unit.FEET_TENTH); else gps.UnAdjZ = coord.Z; } else gps.UnAdjZ = 0; } else gps.UnAdjZ = 0; gps.PolyCN = _Poly.CN; gps.PolyName = _Poly.Name; gps.GroupCN = Values.MainGroup.CN; gps.GroupName = Values.MainGroup.Name; tmpPoints.Add(gps); } _Points.AddRange(tmpPoints); _Polygons.Add(_Poly.CN, _Poly); polyCount++; } } //Close and free up any resources shapeFileDataReader.Close(); shapeFileDataReader.Dispose(); } foreach (TtPolygon poly in _Polygons.Values) dal.InsertPolygon(poly); dal.InsertPoints(_Points); PolygonAdjuster.Adjust(dal); } catch (Exception ex) { TtUtils.WriteError(ex.Message, "DataImport:ImportShapes", ex.StackTrace); return false; } return true; }