public DefaultTerrainElevationSource(Dataset databaseDataset, double lat, double lon, uint size, uint lod, float unitScale)
            {
                if (databaseDataset == null)
                {
                    throw new ArgumentNullException("databaseDataset");
                }

                // IDisposable referenced
                _DatabaseDataset = databaseDataset;
                _DatabaseDataset.IncRef();

                // Determine current position
                double[] datasetTransform = new double[6], datasetInvTransform = new double[6];
                _DatabaseDataset.GetGeoTransform(datasetTransform);
                Gdal.InvGeoTransform(datasetTransform, datasetInvTransform);

                double xCurrentPosition, yCurrentPosition;

                Gdal.ApplyGeoTransform(datasetInvTransform, lon, lat, out xCurrentPosition, out yCurrentPosition);

                // Let the higher levels to be pixel aligned
                int x = (int)Math.Floor(xCurrentPosition), y = (int)Math.Floor(yCurrentPosition);

                _CurrentTexPosition = _OriginPosition = new Vertex2d(x, y);

                Latitude  = lat;
                Longitude = lon;
                Lod       = lod;
                UnitScale = unitScale;

                _TerrainElevation = new Image(PixelLayout.GRAY16S, size, size);
                _TerrainElevation.IncRef();
            }
Example #2
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Curve> boundary = new List <Curve>();

            DA.GetDataList <Curve>(0, boundary);

            string IMG_file = "";

            DA.GetData <string>("IMG Location", ref IMG_file);

            /*
             * //Does not work with HGT files
             *
             * byte[] imageBuffer;
             *
             * using (FileStream fs = new FileStream(IMG_file, FileMode.Open, FileAccess.Read))
             * {
             *    using (BinaryReader br = new BinaryReader(fs))
             *    {
             *        long numBytes = new FileInfo(IMG_file).Length;
             *        imageBuffer = br.ReadBytes((int)numBytes);
             *        br.Close();
             *        fs.Close();
             *    }
             * }
             */

            RESTful.GdalConfiguration.ConfigureGdal();
            OSGeo.GDAL.Gdal.AllRegister();

            //string memFilename = "/vsimem/inmemfile";
            //Gdal.FileFromMemBuffer(memFilename, imageBuffer);

            Dataset ds = Gdal.Open(IMG_file, Access.GA_ReadOnly);

            OSGeo.GDAL.Driver drv = ds.GetDriver();


            if (ds == null)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The vector datasource was unreadable by this component. It may not a valid file type for this component or otherwise null/empty.");
                return;
            }


            ///Get the spatial reference of the input raster file and set to WGS84 if not known
            ///Set up transform from source to WGS84
            OSGeo.OSR.SpatialReference sr = new SpatialReference(Osr.SRS_WKT_WGS84);
            if (ds.GetProjection() == null)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Coordinate Reference System (CRS) is missing.  CRS set automatically set to WGS84.");
            }

            else
            {
                sr = new SpatialReference(ds.GetProjection());
                if (sr.Validate() != 0)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Coordinate Reference System (CRS) is unknown or unsupported.  CRS set automatically set to WGS84.");
                    sr.SetWellKnownGeogCS("WGS84");
                }

                else
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Data source SRS: EPSG:" + sr.GetAttrValue("AUTHORITY", 1));
                }
            }

            //OSGeo.OSR.SpatialReference sr = new SpatialReference(ds.GetProjection());
            OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
            dst.SetWellKnownGeogCS("WGS84");
            OSGeo.OSR.CoordinateTransformation coordTransform = new OSGeo.OSR.CoordinateTransformation(sr, dst);
            OSGeo.OSR.CoordinateTransformation revTransform   = new OSGeo.OSR.CoordinateTransformation(dst, sr);

            double[] adfGeoTransform = new double[6];
            double[] invTransform    = new double[6];
            ds.GetGeoTransform(adfGeoTransform);
            Gdal.InvGeoTransform(adfGeoTransform, invTransform);
            Band band = ds.GetRasterBand(1);

            int width  = ds.RasterXSize;
            int height = ds.RasterYSize;

            //Dataset bounding box
            double oX = adfGeoTransform[0] + adfGeoTransform[1] * 0 + adfGeoTransform[2] * 0;
            double oY = adfGeoTransform[3] + adfGeoTransform[4] * 0 + adfGeoTransform[5] * 0;
            double eX = adfGeoTransform[0] + adfGeoTransform[1] * width + adfGeoTransform[2] * height;
            double eY = adfGeoTransform[3] + adfGeoTransform[4] * width + adfGeoTransform[5] * height;

            ///Transform to WGS84
            double[] extMinPT = new double[3] {
                oX, eY, 0
            };
            double[] extMaxPT = new double[3] {
                eX, oY, 0
            };
            coordTransform.TransformPoint(extMinPT);
            coordTransform.TransformPoint(extMaxPT);
            Point3d dsMin = new Point3d(extMinPT[0], extMinPT[1], extMinPT[2]);
            Point3d dsMax = new Point3d(extMaxPT[0], extMaxPT[1], extMaxPT[2]);

            //Point3d dsMin = new Point3d(oX, eY, 0);
            //Point3d dsMax = new Point3d(eX, oY, 0);
            Rectangle3d dsbox = new Rectangle3d(Plane.WorldXY, Heron.Convert.WGSToXYZ(dsMin), Heron.Convert.WGSToXYZ(dsMax));

            //Declare trees
            GH_Structure <GH_Point>   pointcloud = new GH_Structure <GH_Point>();
            GH_Structure <GH_Integer> rCount     = new GH_Structure <GH_Integer>();
            GH_Structure <GH_Integer> cCount     = new GH_Structure <GH_Integer>();
            GH_Structure <GH_Mesh>    tMesh      = new GH_Structure <GH_Mesh>();

            for (int i = 0; i < boundary.Count; i++)
            {
                if (dsbox.BoundingBox.Contains(boundary[i].GetBoundingBox(true).Min) && (dsbox.BoundingBox.Contains(boundary[i].GetBoundingBox(true).Max)))
                {
                    Point3d min = Heron.Convert.XYZToWGS(boundary[i].GetBoundingBox(true).Corner(true, false, true));
                    Point3d max = Heron.Convert.XYZToWGS(boundary[i].GetBoundingBox(true).Corner(false, true, true));

                    ///Transform to source SRS
                    double[] minR = new double[3] {
                        min.X, min.Y, min.Z
                    };
                    double[] maxR = new double[3] {
                        max.X, max.Y, max.Z
                    };
                    revTransform.TransformPoint(minR);
                    revTransform.TransformPoint(maxR);

                    GH_Path path = new GH_Path(i);

                    // http://gis.stackexchange.com/questions/46893/how-do-i-get-the-pixel-value-of-a-gdal-raster-under-an-ogr-point-without-numpy

                    double ur, uc, lr, lc;

                    Gdal.ApplyGeoTransform(invTransform, minR[0], minR[1], out uc, out ur);
                    Gdal.ApplyGeoTransform(invTransform, maxR[0], maxR[1], out lc, out lr);
                    //Gdal.ApplyGeoTransform(invTransform, min.X, min.Y, out uc, out ur);
                    //Gdal.ApplyGeoTransform(invTransform, max.X, max.Y, out lc, out lr);

                    int Urow = System.Convert.ToInt32(ur);
                    int Ucol = System.Convert.ToInt32(uc);
                    int Lrow = System.Convert.ToInt32(lr) + 1;
                    int Lcol = System.Convert.ToInt32(lc) + 1;
                    rCount.Append(new GH_Integer(Lrow - Urow), path);
                    cCount.Append(new GH_Integer(Lcol - Ucol), path);
                    Mesh           mesh  = new Mesh();
                    List <Point3d> verts = new List <Point3d>();
                    //var vertsParallel = new System.Collections.Concurrent.ConcurrentDictionary<double[][], Point3d>(Environment.ProcessorCount, ((Urow - 1) * (Lrow - 1)));

                    double[] bits = new double[width * height];
                    band.ReadRaster(0, 0, width, height, bits, width, height, 0, 0);

                    for (int col = Ucol; col < Lcol; col++)
                    {
                        for (int row = Urow; row < Lrow; row++)
                        {
                            // equivalent to bits[col][row] if bits is 2-dimension array
                            double pixel = bits[col + row * width];
                            if (pixel < -10000)
                            {
                                pixel = 0;
                            }

                            double gcol = adfGeoTransform[0] + adfGeoTransform[1] * col + adfGeoTransform[2] * row;
                            double grow = adfGeoTransform[3] + adfGeoTransform[4] * col + adfGeoTransform[5] * row;

                            ///convert to WGS84
                            double[] wgsPT = new double[3] {
                                gcol, grow, pixel
                            };
                            coordTransform.TransformPoint(wgsPT);
                            Point3d pt = new Point3d(wgsPT[0], wgsPT[1], wgsPT[2]);

                            //Point3d pt = new Point3d(gcol, grow, pixel);
                            verts.Add(Heron.Convert.WGSToXYZ(pt));
                        }

                        /*Parallel.For(Urow, Lrow - 1, rowP =>
                         *  {
                         *      // equivalent to bits[col][row] if bits is 2-dimension array
                         *      double pixel = bits[col + rowP * width];
                         *      if (pixel < -10000)
                         *      {
                         *          pixel = 0;
                         *      }
                         *
                         *      double gcol = adfGeoTransform[0] + adfGeoTransform[1] * col + adfGeoTransform[2] * rowP;
                         *      double grow = adfGeoTransform[3] + adfGeoTransform[4] * col + adfGeoTransform[5] * rowP;
                         *
                         *      Point3d pt = new Point3d(gcol, grow, pixel);
                         *      vertsParallel[] = Heron.Convert.ToXYZ(pt);
                         *  });
                         * */
                    }

                    //Create meshes
                    //non Parallel
                    mesh.Vertices.AddVertices(verts);
                    //Parallel
                    //mesh.Vertices.AddVertices(vertsParallel.Values);

                    for (int u = 1; u < cCount[path][0].Value; u++)
                    {
                        for (int v = 1; v < rCount[path][0].Value; v++)
                        {
                            mesh.Faces.AddFace(v - 1 + (u - 1) * (Lrow - Urow), v - 1 + u * (Lrow - Urow), v - 1 + u * (Lrow - Urow) + 1, v - 1 + (u - 1) * (Lrow - Urow) + 1);
                            //(k - 1 + (j - 1) * num2, k - 1 + j * num2, k - 1 + j * num2 + 1, k - 1 + (j - 1) * num2 + 1)
                        }
                    }
                    //mesh.Flip(true, true, true);
                    tMesh.Append(new GH_Mesh(mesh), path);
                }

                else
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "One or more boundaries may be outside the bounds of the topo dataset.");
                    //return;
                }
            }
            DA.SetDataTree(0, tMesh);
            DA.SetData(1, dsbox);
        }
            public DefaultTerrainElevationFactory(string databaseRoot, double lat, double lon, uint maxLod)
            {
                if (databaseRoot == null)
                {
                    throw new ArgumentNullException("databaseRoot");
                }

                // Open the dataset.
                try {
                    _DatabaseDataset = Gdal.OpenShared(databaseRoot, Access.GA_ReadOnly);

                    if (_DatabaseDataset.RasterCount != 1)
                    {
                        throw new NotSupportedException();
                    }

                    DatabaseRoot = databaseRoot;

                    using (Band band = _DatabaseDataset.GetRasterBand(1)) {
                        switch (band.GetColorInterpretation())
                        {
                        case ColorInterp.GCI_Undefined:
                            switch (_DatabaseDataset.GetDriver().ShortName)
                            {
                            case "SRTMHGT":
                            case "VRT":
                                break;

                            default:
                                throw new NotSupportedException("unknown GDAL driver");
                            }
                            break;

                        default:
                            throw new NotSupportedException("unknown color interpretation");
                        }
                    }

                    // Determine current position
                    double[] datasetTransform = new double[6], datasetInvTransform = new double[6];
                    _DatabaseDataset.GetGeoTransform(datasetTransform);
                    Gdal.InvGeoTransform(datasetTransform, datasetInvTransform);

                    double xCurrentPosition, yCurrentPosition;
                    Gdal.ApplyGeoTransform(datasetInvTransform, lon, lat, out xCurrentPosition, out yCurrentPosition);

                    // Let the higher levels to be pixel aligned
                    int x = (int)Math.Floor(xCurrentPosition), y = (int)Math.Floor(yCurrentPosition);
                    int maxLodStride = (int)Math.Pow(2.0, maxLod);

                    x -= x % maxLodStride;
                    y -= y % maxLodStride;

                    x = Math.Max(x, 0);
                    y = Math.Max(y, 0);

                    Gdal.ApplyGeoTransform(datasetTransform, x, y, out lon, out lat);

                    Latitude  = lat;
                    Longitude = lon;
                } catch {
                    // Ensure GDAL object disposition
                    if (_DatabaseDataset != null)
                    {
                        _DatabaseDataset.Dispose();
                    }
                    // Exception
                    throw;
                }
            }
Example #4
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Curve> boundary = new List <Curve>();

            DA.GetDataList <Curve>(0, boundary);

            string IMG_file = string.Empty;

            DA.GetData <string>(1, ref IMG_file);

            RESTful.GdalConfiguration.ConfigureGdal();
            OSGeo.GDAL.Gdal.AllRegister();

            Dataset datasource = Gdal.Open(IMG_file, Access.GA_ReadOnly);

            OSGeo.GDAL.Driver drv = datasource.GetDriver();


            if (datasource == null)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The vector datasource was unreadable by this component. It may not a valid file type for this component or otherwise null/empty.");
                return;
            }

            ///Get info about image
            string        srcInfo     = string.Empty;
            List <string> infoOptions = new List <string> {
                "-stats"
            };

            srcInfo = Gdal.GDALInfo(datasource, new GDALInfoOptions(infoOptions.ToArray()));


            ///Get the spatial reference of the input raster file and set to WGS84 if not known
            ///Set up transform from source to WGS84
            OSGeo.OSR.SpatialReference sr = new SpatialReference(Osr.SRS_WKT_WGS84);
            if (datasource.GetProjection() == null)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Coordinate Reference System (CRS) is missing.  CRS set automatically set to WGS84.");
            }

            else
            {
                sr = new SpatialReference(datasource.GetProjection());

                if (sr.Validate() != 0)
                {
                    ///Check if SRS needs to be converted from ESRI format to WKT to avoid error:
                    ///"No translation for Lambert_Conformal_Conic to PROJ.4 format is known."
                    ///https://gis.stackexchange.com/questions/128266/qgis-error-6-no-translation-for-lambert-conformal-conic-to-proj-4-format-is-kn
                    SpatialReference srEsri = sr;
                    srEsri.MorphFromESRI();
                    string projEsri = string.Empty;
                    srEsri.ExportToWkt(out projEsri);

                    ///If no SRS exists, check Ground Control Points SRS
                    SpatialReference srGCP   = new SpatialReference(datasource.GetGCPProjection());
                    string           projGCP = string.Empty;
                    srGCP.ExportToWkt(out projGCP);

                    if (!string.IsNullOrEmpty(projEsri))
                    {
                        datasource.SetProjection(projEsri);
                        sr = srEsri;
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) morphed form ESRI format.");
                    }
                    else if (!string.IsNullOrEmpty(projGCP))
                    {
                        datasource.SetProjection(projGCP);
                        sr = srGCP;
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) set from Ground Control Points (GCPs).");
                    }
                    else
                    {
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) is unknown or unsupported.  SRS assumed to be WGS84." +
                                          "Try setting the SRS with the GdalWarp component using -t_srs EPSG:4326 for the option input.");
                        sr.SetWellKnownGeogCS("WGS84");
                    }
                }

                else
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Data source SRS: EPSG:" + sr.GetAttrValue("AUTHORITY", 1));
                }
            }

            //OSGeo.OSR.SpatialReference sr = new SpatialReference(ds.GetProjection());
            OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
            dst.SetWellKnownGeogCS("WGS84");
            OSGeo.OSR.CoordinateTransformation coordTransform = new OSGeo.OSR.CoordinateTransformation(sr, dst);
            OSGeo.OSR.CoordinateTransformation revTransform   = new OSGeo.OSR.CoordinateTransformation(dst, sr);

            double[] adfGeoTransform = new double[6];
            double[] invTransform    = new double[6];
            datasource.GetGeoTransform(adfGeoTransform);
            Gdal.InvGeoTransform(adfGeoTransform, invTransform);

            int width  = datasource.RasterXSize;
            int height = datasource.RasterYSize;

            ///Dataset bounding box
            double oX = adfGeoTransform[0] + adfGeoTransform[1] * 0 + adfGeoTransform[2] * 0;
            double oY = adfGeoTransform[3] + adfGeoTransform[4] * 0 + adfGeoTransform[5] * 0;
            double eX = adfGeoTransform[0] + adfGeoTransform[1] * width + adfGeoTransform[2] * height;
            double eY = adfGeoTransform[3] + adfGeoTransform[4] * width + adfGeoTransform[5] * height;

            ///Transform to WGS84
            double[] extMinPT = new double[3] {
                oX, eY, 0
            };
            double[] extMaxPT = new double[3] {
                eX, oY, 0
            };
            coordTransform.TransformPoint(extMinPT);
            coordTransform.TransformPoint(extMaxPT);
            Point3d dsMin = new Point3d(extMinPT[0], extMinPT[1], extMinPT[2]);
            Point3d dsMax = new Point3d(extMaxPT[0], extMaxPT[1], extMaxPT[2]);

            Rectangle3d dsbox = new Rectangle3d(Plane.WorldXY, Heron.Convert.WGSToXYZ(dsMin), Heron.Convert.WGSToXYZ(dsMax));

            double pixelWidth  = dsbox.Width / width;
            double pixelHeight = dsbox.Height / height;

            ///Declare trees
            GH_Structure <GH_Point>   pointcloud = new GH_Structure <GH_Point>();
            GH_Structure <GH_Integer> rCount     = new GH_Structure <GH_Integer>();
            GH_Structure <GH_Integer> cCount     = new GH_Structure <GH_Integer>();
            GH_Structure <GH_Mesh>    tMesh      = new GH_Structure <GH_Mesh>();

            for (int i = 0; i < boundary.Count; i++)
            {
                GH_Path path = new GH_Path(i);

                Curve clippingBoundary = boundary[i];

                if (!clip)
                {
                    clippingBoundary = dsbox.ToNurbsCurve();
                }

                string clippedTopoFile = "/vsimem/topoclipped.tif";

                if (!(dsbox.BoundingBox.Contains(clippingBoundary.GetBoundingBox(true).Min) && (dsbox.BoundingBox.Contains(clippingBoundary.GetBoundingBox(true).Max))) && clip)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "One or more boundaries may be outside the bounds of the topo dataset.");
                }

                ///Offsets to mesh/boundary based on pixel size
                Point3d clipperMinPreAdd  = clippingBoundary.GetBoundingBox(true).Corner(true, false, true);
                Point3d clipperMinPostAdd = new Point3d(clipperMinPreAdd.X, clipperMinPreAdd.Y, clipperMinPreAdd.Z);
                Point3d clipperMin        = Heron.Convert.XYZToWGS(clipperMinPostAdd);

                Point3d clipperMaxPreAdd = clippingBoundary.GetBoundingBox(true).Corner(false, true, true);
                ///add/subtract pixel width if desired to get closer to boundary
                Point3d clipperMaxPostAdd = new Point3d();
                Point3d clipperMax        = new Point3d();
                if (clip)
                {
                    clipperMaxPostAdd = new Point3d(clipperMaxPreAdd.X + pixelWidth, clipperMaxPreAdd.Y - pixelHeight, clipperMaxPreAdd.Z);
                    clipperMax        = Heron.Convert.XYZToWGS(clipperMaxPostAdd);
                }
                else
                {
                    clipperMaxPostAdd = new Point3d(clipperMaxPreAdd.X, clipperMaxPreAdd.Y, clipperMaxPreAdd.Z);
                    clipperMax        = Heron.Convert.XYZToWGS(clipperMaxPostAdd);
                }


                double lonWest  = clipperMin.X;
                double lonEast  = clipperMax.X;
                double latNorth = clipperMin.Y;
                double latSouth = clipperMax.Y;

                var translateOptions = new[]
                {
                    "-of", "GTiff",
                    "-a_nodata", "0",
                    "-projwin_srs", "WGS84",
                    "-projwin", $"{lonWest}", $"{latNorth}", $"{lonEast}", $"{latSouth}"
                };

                using (Dataset clippedDataset = Gdal.wrapper_GDALTranslate(clippedTopoFile, datasource, new GDALTranslateOptions(translateOptions), null, null))
                {
                    Band band = clippedDataset.GetRasterBand(1);
                    width  = clippedDataset.RasterXSize;
                    height = clippedDataset.RasterYSize;
                    clippedDataset.GetGeoTransform(adfGeoTransform);
                    Gdal.InvGeoTransform(adfGeoTransform, invTransform);

                    rCount.Append(new GH_Integer(height), path);
                    cCount.Append(new GH_Integer(width), path);
                    Mesh           mesh  = new Mesh();
                    List <Point3d> verts = new List <Point3d>();
                    //var vertsParallel = new System.Collections.Concurrent.ConcurrentDictionary<double[][], Point3d>(Environment.ProcessorCount, ((Urow - 1) * (Lrow - 1)));

                    double[] bits = new double[width * height];
                    band.ReadRaster(0, 0, width, height, bits, width, height, 0, 0);

                    for (int col = 0; col < width; col++)
                    {
                        for (int row = 0; row < height; row++)
                        {
                            // equivalent to bits[col][row] if bits is 2-dimension array
                            double pixel = bits[col + row * width];
                            if (pixel < -10000)
                            {
                                pixel = 0;
                            }

                            double gcol = adfGeoTransform[0] + adfGeoTransform[1] * col + adfGeoTransform[2] * row;
                            double grow = adfGeoTransform[3] + adfGeoTransform[4] * col + adfGeoTransform[5] * row;

                            ///convert to WGS84
                            double[] wgsPT = new double[3] {
                                gcol, grow, pixel
                            };
                            coordTransform.TransformPoint(wgsPT);
                            Point3d pt = new Point3d(wgsPT[0], wgsPT[1], wgsPT[2]);

                            verts.Add(Heron.Convert.WGSToXYZ(pt));
                        }

                        /*Parallel.For(Urow, Lrow - 1, rowP =>
                         *  {
                         *      // equivalent to bits[col][row] if bits is 2-dimension array
                         *      double pixel = bits[col + rowP * width];
                         *      if (pixel < -10000)
                         *      {
                         *          pixel = 0;
                         *      }
                         *
                         *      double gcol = adfGeoTransform[0] + adfGeoTransform[1] * col + adfGeoTransform[2] * rowP;
                         *      double grow = adfGeoTransform[3] + adfGeoTransform[4] * col + adfGeoTransform[5] * rowP;
                         *
                         *      Point3d pt = new Point3d(gcol, grow, pixel);
                         *      vertsParallel[] = Heron.Convert.ToXYZ(pt);
                         *  });
                         * */
                    }

                    //Create meshes
                    //non Parallel
                    mesh.Vertices.AddVertices(verts);
                    //Parallel
                    //mesh.Vertices.AddVertices(vertsParallel.Values);

                    for (int u = 1; u < cCount[path][0].Value; u++)
                    {
                        for (int v = 1; v < rCount[path][0].Value; v++)
                        {
                            mesh.Faces.AddFace(v - 1 + (u - 1) * (height), v - 1 + u * (height), v - 1 + u * (height) + 1, v - 1 + (u - 1) * (height) + 1);
                            //(k - 1 + (j - 1) * num2, k - 1 + j * num2, k - 1 + j * num2 + 1, k - 1 + (j - 1) * num2 + 1)
                        }
                    }

                    //mesh.Flip(true, true, true);
                    tMesh.Append(new GH_Mesh(mesh), path);

                    band.Dispose();
                }
                Gdal.Unlink("/vsimem/topoclipped.tif");
            }

            datasource.Dispose();

            DA.SetDataTree(0, tMesh);
            DA.SetData(1, dsbox);
            DA.SetData(2, srcInfo);
        }
Example #5
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Curve boundary = null;

            DA.GetData <Curve>(0, ref boundary);

            string sourceFileLocation = string.Empty;

            DA.GetData <string>(1, ref sourceFileLocation);

            string clippedLocation = string.Empty;

            DA.GetData <string>(2, ref clippedLocation);

            RESTful.GdalConfiguration.ConfigureGdal();
            OSGeo.GDAL.Gdal.AllRegister();
            ///Specific settings for getting WMS images
            OSGeo.GDAL.Gdal.SetConfigOption("GDAL_HTTP_UNSAFESSL", "YES");
            OSGeo.GDAL.Gdal.SetConfigOption("GDAL_SKIP", "WMS");

            ///Read in the raster data
            Dataset datasource = Gdal.Open(sourceFileLocation, Access.GA_ReadOnly);

            OSGeo.GDAL.Driver drv = datasource.GetDriver();

            string srcInfo = string.Empty;

            if (datasource == null)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The raster datasource was unreadable by this component. It may not a valid file type for this component or otherwise null/empty.");
                return;
            }


            ///Get the spatial reference of the input raster file and set to WGS84 if not known
            ///Set up transform from source to WGS84
            OSGeo.OSR.SpatialReference sr = new SpatialReference(Osr.SRS_WKT_WGS84);

            if (datasource.GetProjection() == null)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) is missing.  SRS set automatically set to WGS84.");
            }

            else
            {
                sr = new SpatialReference(datasource.GetProjection());

                if (sr.Validate() != 0)
                {
                    ///Check if SRS needs to be converted from ESRI format to WKT to avoid error:
                    ///"No translation for Lambert_Conformal_Conic to PROJ.4 format is known."
                    ///https://gis.stackexchange.com/questions/128266/qgis-error-6-no-translation-for-lambert-conformal-conic-to-proj-4-format-is-kn
                    SpatialReference srEsri = sr;
                    srEsri.MorphFromESRI();
                    string projEsri = string.Empty;
                    srEsri.ExportToWkt(out projEsri);

                    ///If no SRS exists, check Ground Control Points SRS
                    SpatialReference srGCP   = new SpatialReference(datasource.GetGCPProjection());
                    string           projGCP = string.Empty;
                    srGCP.ExportToWkt(out projGCP);

                    if (!string.IsNullOrEmpty(projEsri))
                    {
                        datasource.SetProjection(projEsri);
                        sr = srEsri;
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) morphed form ESRI format.");
                    }
                    else if (!string.IsNullOrEmpty(projGCP))
                    {
                        datasource.SetProjection(projGCP);
                        sr = srGCP;
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) set from Ground Control Points (GCPs).");
                    }
                    else
                    {
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) is unknown or unsupported.  SRS assumed to be WGS84." +
                                          "Try setting the SRS with the GdalWarp component using -t_srs EPSG:4326 for the option input.");
                        sr.SetWellKnownGeogCS("WGS84");
                    }
                }
                else
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Data source SRS: EPSG:" + sr.GetAttrValue("AUTHORITY", 1));
                }
            }

            ///Get info about image
            List <string> infoOptions = new List <string> {
                "-stats"
            };

            srcInfo = Gdal.GDALInfo(datasource, new GDALInfoOptions(infoOptions.ToArray()));

            //OSGeo.OSR.SpatialReference sr = new SpatialReference(ds.GetProjection());
            OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
            dst.SetWellKnownGeogCS("WGS84");
            OSGeo.OSR.CoordinateTransformation coordTransform = new OSGeo.OSR.CoordinateTransformation(sr, dst);
            OSGeo.OSR.CoordinateTransformation revTransform   = new OSGeo.OSR.CoordinateTransformation(dst, sr);

            double[] adfGeoTransform = new double[6];
            double[] invTransform    = new double[6];
            datasource.GetGeoTransform(adfGeoTransform);
            Gdal.InvGeoTransform(adfGeoTransform, invTransform);
            Band band = datasource.GetRasterBand(1);

            int width  = datasource.RasterXSize;
            int height = datasource.RasterYSize;

            ///Dataset bounding box
            double oX = adfGeoTransform[0] + adfGeoTransform[1] * 0 + adfGeoTransform[2] * 0;
            double oY = adfGeoTransform[3] + adfGeoTransform[4] * 0 + adfGeoTransform[5] * 0;
            double eX = adfGeoTransform[0] + adfGeoTransform[1] * width + adfGeoTransform[2] * height;
            double eY = adfGeoTransform[3] + adfGeoTransform[4] * width + adfGeoTransform[5] * height;

            ///Transform to WGS84.
            ///TODO: Allow for UserSRS
            double[] extMinPT = new double[3] {
                oX, eY, 0
            };
            double[] extMaxPT = new double[3] {
                eX, oY, 0
            };
            coordTransform.TransformPoint(extMinPT);
            coordTransform.TransformPoint(extMaxPT);
            Point3d dsMin = new Point3d(extMinPT[0], extMinPT[1], extMinPT[2]);
            Point3d dsMax = new Point3d(extMaxPT[0], extMaxPT[1], extMaxPT[2]);

            ///Get bounding box for entire raster data
            Rectangle3d datasourceBBox = new Rectangle3d(Plane.WorldXY, Heron.Convert.WGSToXYZ(dsMin), Heron.Convert.WGSToXYZ(dsMax));


            ///https://gis.stackexchange.com/questions/312440/gdal-translate-bilinear-interpolation
            ///set output to georeferenced tiff as a catch-all
            string clippedRasterFile = clippedLocation + Path.GetFileNameWithoutExtension(sourceFileLocation) + "_clipped.tif";
            string previewPNG        = clippedLocation + Path.GetFileNameWithoutExtension(sourceFileLocation) + "_preview.png";

            AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Original Resolution: " + datasource.RasterXSize.ToString() + "x" + datasource.RasterYSize.ToString());

            if (boundary != null)
            {
                Point3d clipperMin = Heron.Convert.XYZToWGS(boundary.GetBoundingBox(true).Corner(true, false, true));
                Point3d clipperMax = Heron.Convert.XYZToWGS(boundary.GetBoundingBox(true).Corner(false, true, true));

                double lonWest  = clipperMin.X;
                double lonEast  = clipperMax.X;
                double latNorth = clipperMin.Y;
                double latSouth = clipperMax.Y;

                ///GDALTranslate should also be its own component with full control over options
                var translateOptions = new[]
                {
                    "-of", "GTiff",
                    //"-a_nodata", "0",
                    "-projwin_srs", "WGS84",
                    "-projwin", $"{lonWest}", $"{latNorth}", $"{lonEast}", $"{latSouth}"
                };

                using (Dataset clippedDataset = Gdal.wrapper_GDALTranslate(clippedRasterFile, datasource, new GDALTranslateOptions(translateOptions), null, null))
                {
                    Dataset previewDataset = Gdal.wrapper_GDALTranslate(previewPNG, clippedDataset, null, null, null);

                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Clipped Resolution: " + clippedDataset.RasterXSize.ToString() + "x" + datasource.RasterYSize.ToString());

                    ///clean up
                    clippedDataset.FlushCache();
                    clippedDataset.Dispose();
                    previewDataset.FlushCache();
                    previewDataset.Dispose();

                    AddPreviewItem(previewPNG, BBoxToRect(boundary.GetBoundingBox(true)));
                }
            }

            else
            {
                Dataset previewDataset = Gdal.wrapper_GDALTranslate(previewPNG, datasource, null, null, null);

                ///clean up
                previewDataset.FlushCache();
                previewDataset.Dispose();

                AddPreviewItem(previewPNG, datasourceBBox);
            }

            ///clean up
            datasource.FlushCache();
            datasource.Dispose();

            DA.SetData(0, srcInfo);
            DA.SetData(1, datasourceBBox);
            DA.SetData(2, clippedRasterFile);
        }