/// <summary> /// TODO: /// Create the SQL string to insert this map directly into the MapTube maps database. /// </summary> /// <param name="baseUrl">root url of where all the descriptors are going to be copied to e.g. http://www.maptube.org/census2011 </param> /// <param name="DescriptorRelativeUrl">Descriptor url relative to the base e.g. UV01EW/UV01EW_01_desc.xml</param> /// <returns></returns> public string CreateSQLInsert(Uri CSVUri, string GeometryName, string username, string Title, string Keywords, string ShortDescription, string Information, string DescriptorRelativeUrl, MapTubeD.ColourScale cs) { /* * CREATE TABLE[dbo].[maps]( * [mapid] [int] IDENTITY(1,1) NOT NULL, * [username] [nvarchar](24) NULL, * [mapdescription] [nvarchar](255) NULL, * [url] [nvarchar](255) NULL, * [keywords] [nvarchar](255) NULL, * [maptitle] [nvarchar](64) NULL, * [tileurl] [nvarchar](255) NULL, * [maxzoomlevel] [tinyint] NULL, * [minlat] [float] NULL, * [minlon] [float] NULL, * [maxlat] [float] NULL, * [maxlon] [float] NULL, * [colourscale] [nvarchar](max) NULL, * [hits] [int] NULL, * [creationdate] [datetime] NULL, * [lastviewdate] [datetime] NULL, * [information] [nvarchar](max) NULL, * [maptype] [tinyint] NULL, * [isclickable] [bit] NOT NULL, * [timetag] [nvarchar](6) NULL, * [topicality] [real] NULL * ) */ string SQLPattern = "insert into maps (username,mapdescription,url,keywords,maptitle,tileurl,maxzoomlevel,minlat,minlon,maxlat,maxlon,colourscale,hits,creationdate,lastviewdate,information,maptype,isclickable,timetag,topicality)" + " values ('{0}','{1}','{2}','{3}','{4}','{5}',{6},{7},{8},{9},{10},'{11}',{12},'{13}','{14}','{15}',{16},{17},{18},{19});"; float minlat = 0, minlon = 0, maxlat = 0, maxlon = 0; GetExtentsForGeometry(GeometryName, out minlat, out minlon, out maxlat, out maxlon); //note - this does return success or failure... //extract the colourThresholds part from the colourscale XmlDocument doc = new XmlDocument(); doc.LoadXml(cs.toXML()); XmlNode node = doc.SelectSingleNode("/colourscale/colourThresholds"); string csString = node.OuterXml; //todo: data extents and test descriptor url and base url string DescriptorUrl = new Uri(Path.Combine(_baseURL, DescriptorRelativeUrl)).ToString(); string TileUrl = ""; //this could be a pointer to a MapTubeD instance, but nothing uses the default //dates need to be in the format 2016-05-15 21:50:00 return(string.Format(SQLPattern, username, ShortDescription, DescriptorUrl, Keywords, Title, TileUrl, 17, minlat, minlon, maxlat, maxlon, csString, 0, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Information, 2, 1, "NULL", "NULL")); }
/// <summary> /// This takes the data for a map and returns the MapTubeD descriptor and settings for it. /// </summary> public bool CreateMapDescriptor(Uri CSVUri, string UniqueKey, string AreaKey, string GeometryName, string DataField, out MapTubeD.DBJoinDescriptorFile desc, out MapTubeD.ColourScale cs, out MapTubeD.RenderStyle rs) { desc = new MapTubeD.DBJoinDescriptorFile(); desc.AreaKey = AreaKey; desc.Geometry = GeometryName; desc.DataField = DataField; desc.DataURL = UniqueKey + ".csv"; desc.RenderStyleURL = UniqueKey + "_settings.xml"; cs = new MapTubeD.ColourScale(); //we don't actually do anything with the style at this point, so just create and return a new one rs = new MapTubeD.RenderStyle(); //OK, now we need a style... //the rest of this is 'borrowed' from the webmapcreator string[] Headers; MapTube.GIS.DataLoader loader = new MapTube.GIS.DataLoader(); MapTube.GIS.DataLoader.StatusCode Success = loader.LoadCSVData(CSVUri.ToString(), DataField, out Headers); if (Success != MapTube.GIS.DataLoader.StatusCode.FAIL) { bool IsDiscreteData = loader.IsDiscreteData; if (IsDiscreteData) { cs.deleteAllColours(); List <float> Values = loader.GetDiscreteValues; Color[] cols = MapTube.GIS.Colours.FindNamedColours(DiscreteScheme, Values.Count); for (int i = 0; i < Values.Count; i++) { cs.addColour(cols[i], Values[i], Convert.ToString(Values[i])); } } else { //For continuous you need an extra colour float[] breaksvalues = null; int NumClass = 5; bool IsMissingData = false; float MissingValue = 0; //breaksvalues = MapTube.GIS.Jenks.GetBreaks(NumClass, IsMissingData, MissingValue, loader.DataSet); breaksvalues = MapTube.GIS.Quantiles.GetBreaks(NumClass, IsMissingData, MissingValue, loader.DataSet); cs.deleteAllColours(); //This is a really nasty hack and I would like to get rid of it. If two thresholds in the colourscale are equal, //then their positions flip randomly as the list is re-sorted and the colours and descriptions move. //The only way round this is to have a sortable list that maintains the order colours were added in the event that //two thresholds are equal. Here we get around it by moving the threshold by the smallest possible amount we can //get away with. for (int i = 1; i < breaksvalues.Length; i++) { if (breaksvalues[i - 1] == breaksvalues[i]) { //Add small amount to threshold. Remember -ve values and the fact that there are limited bits of precision. breaksvalues[i] = (float)((double)breaksvalues[i] + (Math.Abs((double)breaksvalues[i]) * 0.00000003d)); } } //now assign colours the existing colours to the breaks int MissingDataIndex = -1; //might need it in the future - all this comes from the webmapcreator Color[] cols = MapTube.GIS.Colours.FindNamedColours(SequentialScheme, breaksvalues.Length); for (int i = 0; i < breaksvalues.Length; i++) { string text = ""; //with a continuous colourscale, a colour only represents a specific data value //text = "Q" + i + " : " + breaksvalues[i]; if (i == MissingDataIndex) { text = "Missing Data (x=" + breaksvalues[i] + ")"; } //minimum breaks value condition taking into account missing data might be below it (i.e. i=0 or i=1) else if (((i == 0) && (MissingDataIndex == -1)) || ((i == 1) && (MissingDataIndex == 0))) { text = breaksvalues[i] + " (min) <= x < " + breaksvalues[i + 1]; } //maximum break taking into account missing data might be above it (NOTE i==MissingDataIndex handled above) else if ((i == breaksvalues.Length - 1) || ((i == breaksvalues.Length - 2) && (MissingDataIndex == i + 1))) { text = "x = " + breaksvalues[i] + " (max)"; } //somewhere in the middle case else { text = breaksvalues[i] + " <= x < " + breaksvalues[i + 1]; } cs.addColour(cols[i], breaksvalues[i], text); } } return(true); } return(false); //failed, data not valid }