// Parse our routes and location data into a use able list/struct public static void ParseRouteData(ref Diorama d, string filepath) { string[] fileData = System.IO.File.ReadAllLines(filepath); // First line is headers for (int i = 1; i < fileData.Length; i++) { string s = fileData[i]; string[] lineData = s.Trim().Split(','); string rId = lineData[2]; float rLatitude = float.Parse(lineData[4]); float rLongitude = float.Parse(lineData[5]); // Find our already stored route data int index = d.popByRoute.FindIndex(r => r.routeID.CompareTo(rId) == 0); routeData route = new routeData { routeID = rId, organisms = d.popByRoute[index].organisms, latitude = rLatitude, longitude = rLongitude, }; // Update our stored route with the lat/long info d.popByRoute[index] = route; } }
public routeData Clone() { List <Organism> o = new List <Organism>(); for (int i = 0; i < this.organisms.Count; i++) { o.Add(organisms[i].Clone()); } routeData p = new routeData { routeID = routeID, organisms = o, latitude = latitude, longitude = longitude, pixelX = pixelX, pixelY = pixelY }; return(p); }
/* Runs through our data from BBS and determines counts of birds over * years and routes */ public static void ParseBBSData(ref Diorama d, string filepath) { string[] fileData = System.IO.File.ReadAllLines(filepath); List <routeData> routes = new List <routeData>(); int index; // Deep copy of organisms List <Organism> copyOfOrganisms = new List <Organism>(); for (int i = 0; i < d.organisms.Count; i++) { copyOfOrganisms.Add(d.organisms[i].Clone()); } // First line is text, so start on second for (int i = 1; i < fileData.Length; i++) { string s = fileData[i]; string[] lineData = s.Trim().Split(','); // If we have no info on this route, add it to our list string routeId = lineData[2]; // Get a Deep Copy of our static info List <Organism> currClone = new List <Organism>(); for (int j = 0; j < copyOfOrganisms.Count; j++) { currClone.Add(copyOfOrganisms[j].Clone()); } routeData r = new routeData { routeID = routeId, organisms = currClone }; // Get our current species info int aou = int.Parse(lineData[4]); yearData p = new yearData { year = int.Parse(lineData[3]), numRoutes = 1, count = int.Parse(lineData[5]) }; // Find the animal with the matching aou so we can add data to it for (int k = 0; k < d.organisms.Count; k++) { if (d.organisms[k].aou == aou) { // We have found the matching animal, now we need to see if it // already has data for the year we are on index = d.organisms[k].data.FindIndex(data => data.year == p.year); if (index == -1) { // It did not have existing data, so we add it d.organisms[k].data.Add(p); } else if (d.organisms[k].classification == Classification.bird) { // The data already existed, so now we increment int totalCounts = p.count + d.organisms[k].data[index].count; int totalRoutes = d.organisms[k].data[index].numRoutes + 1; d.organisms[k].data[index] = new yearData { year = p.year, numRoutes = totalRoutes, count = totalCounts }; } } } // See if we already have this route number, if not add it index = routes.FindIndex(route => string.Compare(route.routeID, routeId) == 0); if (index == -1) { routes.Add(r.Clone()); index = routes.Count - 1; } // Get a reference to our routes data List <Organism> o = routes[index].organisms; int organismIndex = o.FindIndex(organism => organism.GetAOU() == aou); if (o[organismIndex].classification == Classification.bird) { // Add data on this bird for our route index = o[organismIndex].data.FindIndex(data => data.year == p.year); if (index == -1) { // It did not have existing data, so we add it o[organismIndex].data.Add(p); } else { // The data already existed, so now we increment int totalCounts = p.count + o[organismIndex].data[index].count; int totalRoutes = o[organismIndex].data[index].numRoutes + 1; o[organismIndex].data[index] = new yearData { year = p.year, numRoutes = totalRoutes, count = totalCounts }; } } } // Now that all data is stored in birds, sort them so they are sequential for (int i = 0; i < d.organisms.Count; i++) { d.organisms[i].data.Sort((d1, d2) => d1.year.CompareTo(d2.year)); } // Sort our birds by year, per route foreach (routeData p in routes) { for (int i = 0; i < p.organisms.Count; i++) { p.organisms[i].data.Sort((d1, d2) => d1.year.CompareTo(d2.year)); } } d.popByRoute = routes; }
public Texture2D Visualize(Diorama d, Texture2D MNTexture2D, Texture2D colormap, int birdIndex, int year, int maxCount) { // Initialization popByYear = new List <extrapPopDataByYear>(); popByRoute = new List <extrapPopDataByRoute>(); List <routeData> rData = d.popByRoute; Texture2D tex = new Texture2D(MNTexture2D.width, MNTexture2D.height); Graphics.CopyTexture(MNTexture2D, tex); // Get our per-year population data foreach (Organism o in d.organisms) { List <int> years = new List <int>(); List <float> extrapolatedCount = new List <float>(); for (int i = 0; i < o.GetPopulationData().Count; i++) { years.Add(o.data[i].year); extrapolatedCount.Add(o.data[i].count / (float)o.data[i].numRoutes); } if (years.Count > 0) { extrapPopDataByYear b = new extrapPopDataByYear { name = o.GetName(), years = years, extrapolatedCount = extrapolatedCount }; popByYear.Add(b); } } // Get extrapolated population by routes for (int i = 0; i < d.popByRoute.Count; i++) { string rId = d.popByRoute[i].routeID; List <extrapPopDataByYear> routePop = new List <extrapPopDataByYear>(); foreach (Organism o in d.popByRoute[i].organisms) { List <int> years = new List <int>(); List <float> extrapolatedCount = new List <float>(); for (int k = 0; k < o.GetPopulationData().Count; k++) { years.Add(o.data[k].year); extrapolatedCount.Add(o.data[k].count / (float)o.data[k].numRoutes); } extrapPopDataByYear b = new extrapPopDataByYear { name = o.GetName(), years = years, extrapolatedCount = extrapolatedCount }; routePop.Add(b); } extrapPopDataByRoute r = new extrapPopDataByRoute { routeId = rId, popByYear = routePop }; popByRoute.Add(r); } // Get extrapolated pixel locations of each route for (int i = 0; i < rData.Count; i++) { int x = ChangeScale_FtoI(0, tex.width - 1, minLong, maxLong, rData[i].longitude); int y = ChangeScale_FtoI(0, tex.height - 1, minLat, maxLat, rData[i].latitude); rData[i] = new routeData { routeID = rData[i].routeID, organisms = rData[i].organisms, latitude = rData[i].latitude, longitude = rData[i].longitude, pixelX = x, pixelY = y }; } // At this point, we now have stored population data by year // We have extrapolated our lat/longitude to pixel coordinates // Now, we want to change all pixels colors by the data at a specific year at all routes // Need a color map Color max = Color.white; Color min = Color.black; Color[] pixels = tex.GetPixels(); Color[] newPixels = new Color[pixels.Length]; float[] values = new float[popByRoute.Count]; float[] inverseDistances = new float[popByRoute.Count]; float[] ratios = new float[popByRoute.Count]; List <float> routeCounts = new List <float>(); // Get our max value found so that we can normalize our colormap for (int i = 0; i < popByRoute.Count; i++) { routeData r = rData[i]; // Find the route int index = popByRoute.FindIndex(route => route.routeId.CompareTo(r.routeID) == 0); // Find yearly data in this route int yearIndex = popByRoute[index].popByYear[birdIndex].years.IndexOf(year); // If it fails, add 0, else add it's pop value if (yearIndex == -1) { routeCounts.Add(0f); } else { routeCounts.Add(popByRoute[index].popByYear[birdIndex].extrapolatedCount[yearIndex]); } } /* * Starting per-pixel calculations */ for (int i = 0; i < pixels.Length; i++) { // We don't want to edit transparent sections of the image, black, or white if (pixels[i].a == 0 || (pixels[i].r < 0.1f && pixels[i].g < 0.1f && pixels[i].b < 0.1f) || (pixels[i].r > 0.9f && pixels[i].g > 0.9f && pixels[i].b > 0.9f)) { newPixels[i] = pixels[i]; continue; } // Initialize pixel value for our Lerp float pixelVal = 0; // Getting our inverse distance relationship values // Further away routes have less impact on pixels color int imgWidth = tex.width; int imgHeight = tex.height; for (int k = 0; k < popByRoute.Count; k++) { int px = rData[k].pixelX; int py = rData[k].pixelY; int x = i % imgWidth; int y = (i - x) / (imgWidth - 1); float dist = (px - x) * (px - x) + (py - y) * (py - y); if (dist == 0) { dist = 1f; } inverseDistances[k] = (1.0f / (dist * dist)); } float totalDist = SumArray(inverseDistances); // Turn these inverseDistances into ratios to multiply by the pixels // Normalize the distances float inverseTotalDist = 1.0f / totalDist; for (int k = 0; k < popByRoute.Count; k++) { ratios[k] = inverseDistances[k] * inverseTotalDist; } // Multiply our pre-computed route population count data by our ratio for this specific pixel for (int k = 0; k < popByRoute.Count; k++) { if (ratios[k] < 0.0001f) { values[k] = 0.0f; continue; } values[k] = (ratios[k] * routeCounts[k]); } // Need to sum it up and Lerp pixelVal = Mathf.Max(Mathf.Min(SumArray(values) / maxCount, 1), 0); newPixels[i] = colormap.GetPixel((colormap.width - 1) - (int)(pixelVal * (colormap.width - 1)), 0); //newPixels[i] = Color.Lerp(Color.black, Color.white, Mathf.Clamp(pixelVal, 0.001f, 0.999f)); } // Apply our pixel colors to our textures tex.SetPixels(newPixels); tex.Apply(); // // Draw our route locations on our texture as well for debugging // for (int i = 0; i < rData.Count; i++) { // int x = rData[i].pixelX; // int y = rData[i].pixelY; // MNTexture2D.SetPixel(x, y, Color.black); // } // MNTexture2D.Apply(); return(tex); }