コード例 #1
0
    public ContourAnimationInfo getContourAnimations(ContourQuery contourQuery)
    {
        List <List <TrendingDataLocation> > frames     = GetFramesFromHistorian(contourQuery);
        PiecewiseLinearFunction             colorScale = GetColorScale(contourQuery);
        Func <double, double> colorFunc = colorScale;

        // The actual startDate is the timestamp of the
        // first frame after contourQuery.GetStartDate()
        DateTime startDate       = contourQuery.GetStartDate();
        int      stepSize        = contourQuery.StepSize;
        int      startTimeOffset = (int)Math.Ceiling((startDate - startDate.Date).TotalMinutes / stepSize);

        startDate = startDate.Date.AddMinutes(startTimeOffset * stepSize);
        double latDif = frames.Min(frame => frame.Max(location => location.Latitude)) - frames.Min(frame => frame.Min(location => location.Latitude));
        double lonDif = frames.Min(frame => frame.Max(location => location.Longitude)) - frames.Min(frame => frame.Min(location => location.Longitude));

        double minLat = frames.Min(frame => frame.Min(location => location.Latitude)) - (latDif * 0.1D);
        double maxLat = frames.Min(frame => frame.Max(location => location.Latitude)) + (latDif * 0.1D);
        double minLng = frames.Min(frame => frame.Min(location => location.Longitude)) - (lonDif * 0.1D);
        double maxLng = frames.Min(frame => frame.Max(location => location.Longitude)) + (lonDif * 0.1D);

        GeoCoordinate topLeft     = new GeoCoordinate(maxLat, minLng);
        GeoCoordinate bottomRight = new GeoCoordinate(minLat, maxLng);

        GSF.Drawing.Point topLeftPoint     = s_crs.Translate(topLeft, contourQuery.Resolution);
        GSF.Drawing.Point bottomRightPoint = s_crs.Translate(bottomRight, contourQuery.Resolution);

        topLeftPoint     = new GSF.Drawing.Point(Math.Floor(topLeftPoint.X), Math.Floor(topLeftPoint.Y));
        bottomRightPoint = new GSF.Drawing.Point(Math.Ceiling(bottomRightPoint.X), Math.Ceiling(bottomRightPoint.Y));
        topLeft          = s_crs.Translate(topLeftPoint, contourQuery.Resolution);
        bottomRight      = s_crs.Translate(bottomRightPoint, contourQuery.Resolution);

        int width  = (int)(bottomRightPoint.X - topLeftPoint.X + 1);
        int height = (int)(bottomRightPoint.Y - topLeftPoint.Y + 1);

        int    animationID;
        string timeZoneID = null;

        using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
        {
            connection.ExecuteNonQuery("INSERT INTO ContourAnimation(ColorScaleName, StartTime, EndTime, StepSize) VALUES({0}, {1}, {2}, {3})", contourQuery.ColorScaleName, contourQuery.GetStartDate(), contourQuery.GetEndDate(), contourQuery.StepSize);
            animationID = connection.ExecuteScalar <int>("SELECT @@IDENTITY");

            if (contourQuery.IncludeWeather)
            {
                timeZoneID = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'XDATimeZone'");
            }
        }

        GSF.Threading.CancellationToken cancellationToken = new GSF.Threading.CancellationToken();
        s_cancellationTokens[animationID] = cancellationToken;

        ProgressCounter progressCounter = new ProgressCounter(frames.Count);

        s_progressCounters[animationID] = progressCounter;

        Action <int> createFrame = i =>
        {
            List <TrendingDataLocation> frame = frames[i];
            IDWFunc idwFunction = GetIDWFunction(contourQuery, frame);
            uint[]  pixelData;

            if (contourQuery.IncludeWeather)
            {
                TimeZoneInfo tzInfo = !string.IsNullOrEmpty(timeZoneID)
                    ? TimeZoneInfo.FindSystemTimeZoneById(timeZoneID)
                    : TimeZoneInfo.Local;

                // Weather data is only available in 5-minute increments
                DateTime frameTime      = TimeZoneInfo.ConvertTimeToUtc(startDate.AddMinutes(stepSize * i), tzInfo);
                double   minutes        = (frameTime - frameTime.Date).TotalMinutes;
                int      weatherMinutes = (int)Math.Ceiling(minutes / 5) * 5;

                NameValueCollection queryString = HttpUtility.ParseQueryString(string.Empty);
                queryString["service"]     = "WMS";
                queryString["request"]     = "GetMap";
                queryString["layers"]      = "nexrad-n0r-wmst";
                queryString["format"]      = "image/png";
                queryString["transparent"] = "true";
                queryString["version"]     = "1.1.1";
                queryString["time"]        = frameTime.Date.AddMinutes(weatherMinutes).ToString("o");
                queryString["height"]      = height.ToString();
                queryString["width"]       = width.ToString();
                queryString["srs"]         = "EPSG:3857";

                GSF.Drawing.Point topLeftProjected     = s_crs.Projection.Project(topLeft);
                GSF.Drawing.Point bottomRightProjected = s_crs.Projection.Project(bottomRight);
                queryString["bbox"] = string.Join(",", topLeftProjected.X, bottomRightProjected.Y, bottomRightProjected.X, topLeftProjected.Y);

                string weatherURL = "http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi?" + queryString.ToString();

                using (WebClient client = new WebClient())
                    using (MemoryStream stream = new MemoryStream(client.DownloadData(weatherURL)))
                        using (Bitmap bitmap = new Bitmap(stream))
                        {
                            pixelData = bitmap.ToPixelData();
                        }
            }
            else
            {
                pixelData = new uint[width * height];
            }

            if (cancellationToken.IsCancelled)
            {
                return;
            }

            for (int x = 0; x < width; x++)
            {
                if (cancellationToken.IsCancelled)
                {
                    return;
                }

                for (int y = 0; y < height; y++)
                {
                    if (cancellationToken.IsCancelled)
                    {
                        return;
                    }

                    if (pixelData[y * width + x] > 0)
                    {
                        continue;
                    }

                    GSF.Drawing.Point offsetPixel       = new GSF.Drawing.Point(topLeftPoint.X + x, topLeftPoint.Y + y);
                    GeoCoordinate     pixelCoordinate   = s_crs.Translate(offsetPixel, contourQuery.Resolution);
                    double            interpolatedValue = idwFunction(pixelCoordinate.Longitude, pixelCoordinate.Latitude);
                    pixelData[y * width + x] = (uint)colorFunc(interpolatedValue);
                }
            }

            if (cancellationToken.IsCancelled)
            {
                return;
            }

            using (Bitmap bitmap = BitmapExtensions.FromPixelData(width, pixelData))
                using (MemoryStream stream = new MemoryStream())
                {
                    bitmap.Save(stream, ImageFormat.Png);

                    using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
                    {
                        connection.ExecuteNonQuery("INSERT INTO ContourAnimationFrame VALUES({0}, {1}, {2})", animationID, i, stream.ToArray());
                    }
                }

            progressCounter.Increment();
        };

        Task.Run(() =>
        {
            ICancellationToken token;
            ProgressCounter counter;
            Parallel.For(0, frames.Count, createFrame);
            s_cancellationTokens.TryRemove(animationID, out token);
            s_progressCounters.TryRemove(animationID, out counter);

            if (cancellationToken.IsCancelled)
            {
                using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
                {
                    connection.ExecuteNonQuery("DELETE FROM ContourAnimationFrame WHERE ContourAnimationID = {0}", animationID);
                    connection.ExecuteNonQuery("DELETE FROM ContourAnimation WHERE ID = {0}", animationID);
                }
            }
        });

        s_cleanUpAnimationOperation.TryRunOnceAsync();

        return(new ContourAnimationInfo()
        {
            AnimationID = animationID,
            ColorDomain = colorScale.Domain,
            ColorRange = colorScale.Range,
            MinLatitude = bottomRight.Latitude,
            MaxLatitude = topLeft.Latitude,
            MinLongitude = topLeft.Longitude,
            MaxLongitude = bottomRight.Longitude,
            Infos = frames.Select((frame, index) => new ContourInfo()
            {
                Locations = frame,
                URL = string.Format("./mapService.asmx/getContourAnimationFrame?animation={0}&frame={1}", animationID, index),
                Date = contourQuery.GetStartDate().AddMinutes(index * contourQuery.StepSize).ToString()
            }).ToList()
        });
    }
コード例 #2
0
    public void getContourTile()
    {
        ContourQuery contourQuery = new ContourQuery()
        {
            StartDate      = HttpContext.Current.Request.QueryString["StartDate"],
            EndDate        = HttpContext.Current.Request.QueryString["EndDate"],
            ColorScaleName = HttpContext.Current.Request.QueryString["ColorScaleName"],
            DataType       = HttpContext.Current.Request.QueryString["DataType"],
            UserName       = HttpContext.Current.Request.QueryString["Username"],
            Meters         = HttpContext.Current.Request.QueryString["Meters"],
            MeterIds       = HttpContext.Current.Request.QueryString["MeterIds"]
        };

        ContourTileData contourTileData = GetContourTileData(contourQuery);

        double minLat = contourTileData.MinLatitude;
        double maxLat = contourTileData.MaxLatitude;
        double minLng = contourTileData.MinLongitude;
        double maxLng = contourTileData.MaxLongitude;

        CoordinateReferenceSystem crs       = s_crs;
        IDWFunc idwFunction                 = contourTileData.IDWFunction;
        Func <double, double> colorFunction = contourTileData.ColorFunction;

        int tileX = Convert.ToInt32(HttpContext.Current.Request.QueryString["x"]);
        int tileY = Convert.ToInt32(HttpContext.Current.Request.QueryString["y"]);
        int zoom  = Convert.ToInt32(HttpContext.Current.Request.QueryString["zoom"]);

        int tileSize = 256;
        int offsetX  = tileSize * tileX;
        int offsetY  = tileSize * tileY;

        uint[] pixelData = new uint[tileSize * tileSize];

        for (int x = 0; x < tileSize; x++)
        {
            GSF.Drawing.Point validationPixel      = new GSF.Drawing.Point(offsetX + x, 0.0D);
            GeoCoordinate     validationCoordinate = crs.Translate(validationPixel, zoom);

            if (validationCoordinate.Longitude < minLng || validationCoordinate.Longitude > maxLng)
            {
                continue;
            }

            for (int y = 0; y < tileSize; y++)
            {
                GSF.Drawing.Point offsetPixel     = new GSF.Drawing.Point(offsetX + x, offsetY + y);
                GeoCoordinate     pixelCoordinate = crs.Translate(offsetPixel, zoom);

                if (pixelCoordinate.Latitude < minLat || pixelCoordinate.Latitude > maxLat)
                {
                    continue;
                }

                double interpolatedValue = idwFunction(pixelCoordinate.Longitude, pixelCoordinate.Latitude);
                uint   color             = (uint)colorFunction(interpolatedValue);
                pixelData[y * tileSize + x] = color;
            }
        }

        using (Bitmap bitmap = BitmapExtensions.FromPixelData(256, pixelData))
        {
            HttpContext.Current.Response.ContentType = "image/png";
            HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename=tile{0}x{1}.png", tileX, tileY));
            bitmap.Save(HttpContext.Current.Response.OutputStream, ImageFormat.Png);
        }
    }