/// <summary>
        /// Match the number of values of two given data structure, modifing the one with less elements. GH_Curve => GH_Plane
        /// </summary>
        /// <param name="refGhCurves"></param>
        /// <param name="inputPlanes"></param>
        /// <param name="outputPlanes"></param>
        /// <returns></returns>
        public static GH_Structure <GH_Plane> PlanesDSFromCurves(GH_Structure <GH_Curve> refGhCurves, GH_Structure <GH_Plane> inputPlanes, GH_Structure <GH_Plane> outputPlanes)
        {
            bool planesTopoEqualCurvesTopo = refGhCurves.TopologyDescription.Equals(inputPlanes.TopologyDescription);

            if (planesTopoEqualCurvesTopo)
            {
                outputPlanes = inputPlanes.Duplicate();
            }
            else
            {
                foreach (GH_Path ghPath in refGhCurves.Paths)
                {
                    for (int i = 0; i < refGhCurves.get_Branch(ghPath).Count; i++)
                    {
                        outputPlanes.Insert(inputPlanes.get_LastItem(true), ghPath, i);
                    }
                }
            }

            return(outputPlanes);
        }
        /// <summary>
        /// Match the number of values of two given data structure, modifing the one with less elements. GH_Breps => GH_Numbers
        /// </summary>
        /// <param name="inGhBreps"></param>
        /// <param name="inGhNums"></param>
        /// <param name="outGhNums"></param>
        /// <returns></returns>
        public static GH_Structure <GH_Number> NumbersDSFromBreps(GH_Structure <GH_Brep> inGhBreps, GH_Structure <GH_Number> inGhNums, GH_Structure <GH_Number> outGhNums)
        {
            bool brepTopoEqualNumsTopo = inGhNums.TopologyDescription.Equals(inGhBreps.TopologyDescription);

            if (brepTopoEqualNumsTopo)
            {
                outGhNums = inGhNums.Duplicate();
            }
            else
            {
                foreach (GH_Path ghPath in inGhBreps.Paths)
                {
                    for (int i = 0; i < inGhBreps.get_Branch(ghPath).Count; i++)
                    {
                        outGhNums.Insert(inGhNums.get_LastItem(true), ghPath, i);
                    }
                }
            }

            return(outGhNums);
        }
        /// <summary>
        /// Match the number of values of two given data structure, modifing the one with less elements. GH_Breps => GH_Boolean
        /// </summary>
        /// <param name="inGhBreps"></param>
        /// <param name="inGhBool"></param>
        /// <param name="outGhBool"></param>
        /// <returns></returns>
        public static GH_Structure <GH_Boolean> BoolDSFromBreps(GH_Structure <GH_Brep> inGhBreps, GH_Structure <GH_Boolean> inGhBool, GH_Structure <GH_Boolean> outGhBool)
        {
            bool brepTopologyEqualBoolTopology = inGhBool.TopologyDescription.Equals(inGhBreps.TopologyDescription);

            if (brepTopologyEqualBoolTopology)
            {
                outGhBool = inGhBool.Duplicate();
            }
            else
            {
                foreach (GH_Path ghPath in inGhBreps.Paths)
                {
                    for (int i = 0; i < inGhBreps.get_Branch(ghPath).Count; i++)
                    {
                        outGhBool.Insert(inGhBool.get_LastItem(true), ghPath, i);
                    }
                }
            }

            return(outGhBool);
        }
Exemple #4
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Curve> boundary = new List <Curve>();

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

            int zoom = -1;

            DA.GetData <int>(1, ref zoom);

            string fileloc = "";

            DA.GetData <string>(2, ref fileloc);
            if (!fileloc.EndsWith(@"\"))
            {
                fileloc = fileloc + @"\";
            }

            string prefix = "";

            DA.GetData <string>(3, ref prefix);
            if (prefix == "")
            {
                prefix = mbSource;
            }

            string URL = mbURL;
            //DA.GetData<string>(4, ref URL);


            string mbToken = "";

            DA.GetData <string>(4, ref mbToken);
            if (mbToken == "")
            {
                string hmbToken = System.Environment.GetEnvironmentVariable("HERONMAPBOXTOKEN");
                if (hmbToken != null)
                {
                    mbToken = hmbToken;
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Using Mapbox token stored in Environment Variable HERONMAPBOXTOKEN.");
                }
                else
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No Mapbox token is specified.  Please get a valid token from mapbox.com");
                    return;
                }
            }

            bool run = false;

            DA.GetData <bool>("Run", ref run);

            GH_Structure <GH_String> mapList  = new GH_Structure <GH_String>();
            GH_Structure <GH_Curve>  imgFrame = new GH_Structure <GH_Curve>();
            GH_Structure <GH_String> tCount   = new GH_Structure <GH_String>();
            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);
                int     tileTotalCount      = 0;
                int     tileDownloadedCount = 0;

                ///Get image frame for given boundary
                if (!boundary[i].GetBoundingBox(true).IsValid)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Boundary is not valid.");
                    return;
                }
                BoundingBox boundaryBox = boundary[i].GetBoundingBox(true);

                ///TODO: look into scaling boundary to get buffer tiles

                ///file path for final image
                string imgPath = fileloc + prefix + "_" + i + ".png";

                //location of final image file
                mapList.Append(new GH_String(imgPath), path);

                //create cache folder for images
                string        cacheLoc      = fileloc + @"HeronCache\";
                List <string> cacheFileLocs = new List <string>();
                if (!Directory.Exists(cacheLoc))
                {
                    Directory.CreateDirectory(cacheLoc);
                }

                //tile bounding box array
                List <Point3d> boxPtList = new List <Point3d>();


                //get the tile coordinates for all tiles within boundary
                var ranges = Convert.GetTileRange(boundaryBox, zoom);
                List <List <int> > tileList = new List <List <int> >();
                var x_range = ranges.XRange;
                var y_range = ranges.YRange;

                if (x_range.Length > 100 || y_range.Length > 100)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "This tile range is too big (more than 100 tiles in the x or y direction). Check your units.");
                    return;
                }

                //cycle through tiles to get bounding box
                for (int y = (int)y_range.Min; y <= y_range.Max; y++)
                {
                    for (int x = (int)x_range.Min; x <= x_range.Max; x++)
                    {
                        //add bounding box of tile to list
                        boxPtList.AddRange(Convert.GetTileAsPolygon(zoom, y, x).ToList());
                        cacheFileLocs.Add(cacheLoc + mbSource.Replace(" ", "") + zoom + x + y + ".png");
                        tileTotalCount = tileTotalCount + 1;
                    }
                }

                tCount.Insert(new GH_String(tileTotalCount + " tiles (" + tileDownloadedCount + " downloaded / " + (tileTotalCount - tileDownloadedCount) + " cached)"), path, 0);

                //bounding box of tile boundaries
                BoundingBox bboxPts = new BoundingBox(boxPtList);

                //convert bounding box to polyline
                List <Point3d> imageCorners = bboxPts.GetCorners().ToList();
                imageCorners.Add(imageCorners[0]);
                imgFrame.Append(new GH_Curve(new Rhino.Geometry.Polyline(imageCorners).ToNurbsCurve()), path);

                //tile range as string for (de)serialization of TileCacheMeta
                string tileRangeString = zoom.ToString()
                                         + x_range[0].ToString()
                                         + y_range[0].ToString()
                                         + x_range[1].ToString()
                                         + y_range[1].ToString();

                //check if the existing final image already covers the boundary.
                //if so, no need to download more or reassemble the cached tiles.
                ///temporarily disable until how to tag images with meta data is figured out

                /*
                 * if (TileCacheMeta == tileRangeString && Convert.CheckCacheImagesExist(cacheFileLocs))
                 * {
                 *  if (File.Exists(imgPath))
                 *  {
                 *      using (Bitmap imageT = new Bitmap(imgPath))
                 *      {
                 *          //System.Drawing.Imaging.PropertyItem prop = imageT.GetPropertyItem(40092);
                 *          //string imgComment = Encoding.Unicode.GetString(prop.Value);
                 *          string imgComment = imageT.GetCommentsFromImage();
                 *          //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, imgComment);
                 *          imageT.Dispose();
                 *          //check to see if tilerange in comments matches current tilerange
                 *          if (imgComment == (mbSource.Replace(" ", "") + tileRangeString))
                 *          {
                 *              AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Using existing topo image.");
                 *
                 *              Mesh eMesh = TopoMeshFromImage(imgPath, boundaryBox, zoom);
                 *              tMesh.Append(new GH_Mesh(eMesh), path);
                 *              continue;
                 *          }
                 *
                 *      }
                 *
                 *  }
                 *
                 * }
                 */


                ///Query Mapbox URL
                ///download all tiles within boundary
                ///merge tiles into one bitmap

                ///API to query
                ///string mbURL = "https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}@2x.pngraw?access_token=" + mbToken;
                string mbURLauth = mbURL + mbToken;


                ///Do the work of assembling image
                ///setup final image container bitmap
                int    fImageW    = ((int)x_range.Length + 1) * 512;
                int    fImageH    = ((int)y_range.Length + 1) * 512;
                Bitmap finalImage = new Bitmap(fImageW, fImageH, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                int imgPosW = 0;
                int imgPosH = 0;

                if (run == true)
                {
                    using (Graphics g = Graphics.FromImage(finalImage))
                    {
                        g.Clear(Color.Black);
                        for (int y = (int)y_range.Min; y <= (int)y_range.Max; y++)
                        {
                            for (int x = (int)x_range.Min; x <= (int)x_range.Max; x++)
                            {
                                //create tileCache name
                                string tileCache    = mbSource.Replace(" ", "") + zoom + x + y + ".png";
                                string tileCahceLoc = cacheLoc + tileCache;

                                //check cache folder to see if tile image exists locally
                                if (File.Exists(tileCahceLoc))
                                {
                                    Bitmap tmpImage = new Bitmap(Image.FromFile(tileCahceLoc));
                                    //add tmp image to final
                                    g.DrawImage(tmpImage, imgPosW * 512, imgPosH * 512);
                                    tmpImage.Dispose();
                                }

                                else
                                {
                                    tileList.Add(new List <int> {
                                        zoom, y, x
                                    });
                                    string urlAuth = Convert.GetZoomURL(x, y, zoom, mbURLauth);
                                    System.Net.WebClient client = new System.Net.WebClient();
                                    client.DownloadFile(urlAuth, tileCahceLoc);
                                    Bitmap tmpImage = new Bitmap(Image.FromFile(tileCahceLoc));
                                    client.Dispose();

                                    //add tmp image to final
                                    g.DrawImage(tmpImage, imgPosW * 512, imgPosH * 512);
                                    tmpImage.Dispose();
                                    tileDownloadedCount = tileDownloadedCount + 1;
                                }

                                //increment x insert position, goes left to right
                                imgPosW++;
                            }
                            //increment y insert position, goes top to bottom
                            imgPosH++;
                            imgPosW = 0;
                        }
                        //garbage collection
                        g.Dispose();

                        //add tile range meta data to image comments
                        finalImage.AddCommentsToPNG(mbSource.Replace(" ", "") + tileRangeString);

                        //save out assembled image
                        finalImage.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);
                    }
                }

                //garbage collection
                finalImage.Dispose();

                //add to tile count total
                tCount.Insert(new GH_String(tileTotalCount + " tiles (" + tileDownloadedCount + " downloaded / " + (tileTotalCount - tileDownloadedCount) + " cached)"), path, 0);


                Mesh nMesh = TopoMeshFromImage(imgPath, boundaryBox, zoom);

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

                //write out new tile range metadata for serialization
                TileCacheMeta = tileRangeString;
            }

            DA.SetDataTree(0, mapList);
            DA.SetDataTree(1, imgFrame);
            DA.SetDataTree(2, tCount);
            DA.SetDataTree(3, tMesh);
            DA.SetDataList(4, "copyright Mapbox");
        }
Exemple #5
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            #region INPUTS
            // import silkwormSettings file
            List<string> silkwormSettings = new List<string>();
            if (!DA.GetDataList(0, silkwormSettings)) return;

            List<GH_ObjectWrapper> things = new List<GH_ObjectWrapper>();
            if (!DA.GetDataList(1, things)) return;

            // import Silkworm Movement
            #endregion

            SilkwormUtility sUtil = new SilkwormUtility();
            Dictionary<string, string> Settings = sUtil.convertSettings(silkwormSettings);

            #region Optional Variables
            int shell = -999;
            if (!DA.GetData(4, ref shell)) { }
            double layerheight = -999;
            if (!DA.GetData(3, ref layerheight)) { }
            //bool detect = false;
            //if (!DA.GetData(5, ref detect)) { }
            List<Plane> sliceplanes = new List<Plane>();
            if (!DA.GetDataList(2, sliceplanes)) { }

            if (shell == -999)
            {
                shell = int.Parse(Settings["perimeters"]);
            }
            if (layerheight == -999)
            {
                layerheight = double.Parse(Settings["layer_height"]);
            }
            if (sliceplanes.Count<1)
            {
                sliceplanes.Add(Plane.WorldXY);
            }

            #endregion

            List<Brep> Breps = new List<Brep>();

            List<Mesh> Meshes = new List<Mesh>();

            SilkwormSkein skein = new SilkwormSkein();

            #region Sort Types
            foreach (GH_ObjectWrapper obj in things)
            {
                if (obj.Value is GH_Brep)
                {
                    Brep brep = null;
                    GH_Convert.ToBrep(obj.Value, ref brep, GH_Conversion.Both);

                    Breps.Add(brep);
                    continue;

                }

                if (obj.Value is GH_Mesh)
                {
                    Mesh mesh = null;
                    GH_Convert.ToMesh(obj.Value, ref mesh, GH_Conversion.Both);
                    Meshes.Add(mesh);

                    continue;
                }
            }
            #endregion

            if (Breps.Count>0)
            {

                skein = new SilkwormSkein(Settings, Breps, sliceplanes, shell, layerheight);
                skein.BrepSlice(false);

            }

            if (Meshes.Count > 0)
            {

                //TODO
            }

            //Reflect Errors and Warnings

                foreach (string message in skein.ErrorMessages)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, message);

                }
                foreach (string message in skein.WarningMessages)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, message);

                }

            List<Curve>[] openregions = skein.openRegions;

            List<Brep>[] rRegions = skein.Regions;
            List<Brep>[] rPerimeterR = skein.regionPerimeter;
            List<Brep>[]  rInfillR = skein.regionInfill;

            GH_Structure<GH_Brep> Regions = new GH_Structure<GH_Brep>();

            GH_Structure<GH_Curve> openRegions = new GH_Structure<GH_Curve>();

            #region Add Regions to GH_Structure

            if (rRegions.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < rRegions.Length; i++)
                {

                    if (rRegions[i] != null)
                        {
                    for (int j = 0; j < rRegions[i].Count; j++)
                    {

                            GH_Brep gShapes = new GH_Brep(rRegions[i][j]);
                            Regions.Insert(gShapes, new GH_Path(i, 0), j);
                        }

                    }
                }
            }
            if (rPerimeterR.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < rPerimeterR.Length; i++)
                {
            if (rPerimeterR[i] != null)
                        {
                    for (int j = 0; j < rPerimeterR[i].Count; j++)
                    {

                            GH_Brep gShapes = new GH_Brep(rPerimeterR[i][j]);
                            Regions.Insert(gShapes, new GH_Path(i, 1), j);
                        }

                    }
                }
            }
            if (rInfillR.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < rInfillR.Length; i++)
                {
            if (rInfillR[i] != null)
                        {
                    for (int j = 0; j < rInfillR[i].Count; j++)
                    {

                            GH_Brep gShapes = new GH_Brep(rInfillR[i][j]);
                            Regions.Insert(gShapes, new GH_Path(i, 2), j);
                        }

                    }
                }
            }

            if (openregions.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < openregions.Length; i++)
                {
            if (openregions[i] != null)
                        {
                    for (int j = 0; j < openregions[i].Count; j++)
                    {

                            GH_Curve gShapes = new GH_Curve(openregions[i][j]);
                            openRegions.Insert(gShapes, new GH_Path(i), j);
                        }

                    }
                }
            }
            //TODO
            //Add Overhang and Bridges

            #endregion

            #region Add Open Regions to GH_Structure
            if (openregions.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < openregions.Length; i++)
                {

                    for (int j = 0; j < openregions[i].Count; j++)
                    {

                        if (openregions[i][j] != null)
                        {

                            SilkwormSegment segment = new SilkwormSegment(openregions[i][j]);
                            Curve curve = segment.Pline.ToNurbsCurve();
                            GH_Curve gShapes = new GH_Curve(curve);
                            openRegions.Insert(gShapes, new GH_Path(i), j);
                        }

                    }
                }
            }
            #endregion

            #region OUTPUT

            if (!DA.SetDataTree(0, Regions)) { return; }
            if (!DA.SetDataTree(1, openRegions)) { return; }

            #endregion
        }
Exemple #6
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            #region INPUTS
            // import silkwormSettings file
            List <string> silkwormSettings = new List <string>();
            if (!DA.GetDataList(0, silkwormSettings))
            {
                return;
            }

            List <GH_ObjectWrapper> things = new List <GH_ObjectWrapper>();
            if (!DA.GetDataList(1, things))
            {
                return;
            }


            // import Silkworm Movement
            #endregion


            SilkwormUtility             sUtil    = new SilkwormUtility();
            Dictionary <string, string> Settings = sUtil.convertSettings(silkwormSettings);

            #region Optional Variables
            int shell = -999;
            if (!DA.GetData(4, ref shell))
            {
            }
            double layerheight = -999;
            if (!DA.GetData(3, ref layerheight))
            {
            }
            //bool detect = false;
            //if (!DA.GetData(5, ref detect)) { }
            List <Plane> sliceplanes = new List <Plane>();
            if (!DA.GetDataList(2, sliceplanes))
            {
            }

            if (shell == -999)
            {
                shell = int.Parse(Settings["perimeters"]);
            }
            if (layerheight == -999)
            {
                layerheight = double.Parse(Settings["layer_height"]);
            }
            if (sliceplanes.Count < 1)
            {
                sliceplanes.Add(Plane.WorldXY);
            }

            #endregion

            List <Brep> Breps = new List <Brep>();


            List <Mesh> Meshes = new List <Mesh>();

            SilkwormSkein skein = new SilkwormSkein();

            #region Sort Types
            foreach (GH_ObjectWrapper obj in things)
            {
                if (obj.Value is GH_Brep)
                {
                    Brep brep = null;
                    GH_Convert.ToBrep(obj.Value, ref brep, GH_Conversion.Both);

                    Breps.Add(brep);
                    continue;
                }

                if (obj.Value is GH_Mesh)
                {
                    Mesh mesh = null;
                    GH_Convert.ToMesh(obj.Value, ref mesh, GH_Conversion.Both);
                    Meshes.Add(mesh);

                    continue;
                }
            }
            #endregion


            if (Breps.Count > 0)
            {
                skein = new SilkwormSkein(Settings, Breps, sliceplanes, shell, layerheight);
                skein.BrepSlice(false);
            }


            if (Meshes.Count > 0)
            {
                //TODO
            }

            //Reflect Errors and Warnings

            foreach (string message in skein.ErrorMessages)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, message);
            }
            foreach (string message in skein.WarningMessages)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, message);
            }

            List <Curve>[] openregions = skein.openRegions;

            List <Brep>[] rRegions    = skein.Regions;
            List <Brep>[] rPerimeterR = skein.regionPerimeter;
            List <Brep>[] rInfillR    = skein.regionInfill;

            GH_Structure <GH_Brep> Regions = new GH_Structure <GH_Brep>();

            GH_Structure <GH_Curve> openRegions = new GH_Structure <GH_Curve>();


            #region Add Regions to GH_Structure

            if (rRegions.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < rRegions.Length; i++)
                {
                    if (rRegions[i] != null)
                    {
                        for (int j = 0; j < rRegions[i].Count; j++)
                        {
                            GH_Brep gShapes = new GH_Brep(rRegions[i][j]);
                            Regions.Insert(gShapes, new GH_Path(i, 0), j);
                        }
                    }
                }
            }
            if (rPerimeterR.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < rPerimeterR.Length; i++)
                {
                    if (rPerimeterR[i] != null)
                    {
                        for (int j = 0; j < rPerimeterR[i].Count; j++)
                        {
                            GH_Brep gShapes = new GH_Brep(rPerimeterR[i][j]);
                            Regions.Insert(gShapes, new GH_Path(i, 1), j);
                        }
                    }
                }
            }
            if (rInfillR.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < rInfillR.Length; i++)
                {
                    if (rInfillR[i] != null)
                    {
                        for (int j = 0; j < rInfillR[i].Count; j++)
                        {
                            GH_Brep gShapes = new GH_Brep(rInfillR[i][j]);
                            Regions.Insert(gShapes, new GH_Path(i, 2), j);
                        }
                    }
                }
            }

            if (openregions.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < openregions.Length; i++)
                {
                    if (openregions[i] != null)
                    {
                        for (int j = 0; j < openregions[i].Count; j++)
                        {
                            GH_Curve gShapes = new GH_Curve(openregions[i][j]);
                            openRegions.Insert(gShapes, new GH_Path(i), j);
                        }
                    }
                }
            }
            //TODO
            //Add Overhang and Bridges

            #endregion


            #region Add Open Regions to GH_Structure
            if (openregions.GetUpperBound(0) > 1)
            {
                for (int i = 0; i < openregions.Length; i++)
                {
                    for (int j = 0; j < openregions[i].Count; j++)
                    {
                        if (openregions[i][j] != null)
                        {
                            SilkwormSegment segment = new SilkwormSegment(openregions[i][j]);
                            Curve           curve   = segment.Pline.ToNurbsCurve();
                            GH_Curve        gShapes = new GH_Curve(curve);
                            openRegions.Insert(gShapes, new GH_Path(i), j);
                        }
                    }
                }
            }
            #endregion

            #region OUTPUT

            if (!DA.SetDataTree(0, Regions))
            {
                return;
            }
            if (!DA.SetDataTree(1, openRegions))
            {
                return;
            }

            #endregion
        }
Exemple #7
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //bool inputLock = false;
            string key = "Leopard(" + this.InstanceGuid + ")";
            GH_Structure <IGH_GeometricGoo> inGeoTree;

            if (!DA.GetDataTree <IGH_GeometricGoo>(0, out inGeoTree))
            {
                return;
            }

            //clear all stored selection
            if (resetStoredPath)
            {
                storedPath.Clear();
            }

            //delete the preview baked objects
            if (!freezePreviewObjects)
            {
                RemovePreviewObjects();
            }

            //generate the preview baked objects
            if (!inputLock && (generatePreview || !freezePreviewObjects))
            {
                GeneratePreViewObjectsI(inGeoTree);                                                          // && !freezePreviewObjects)
            }
            //happens when unlock
            //if (addSelection)
            //    SelectStoredPathObj(storedPath);

            GH_Structure <GH_String> pathTree = new GH_Structure <GH_String>(); //a tree that the data stored is its path

            for (int i = 0; i < inGeoTree.PathCount; i++)
            {
                string path = inGeoTree.Paths[i].ToString();
                for (int j = 0; j < inGeoTree.Branches[i].Count; j++)
                {
                    string str = path + "(" + j.ToString() + ")";
                    pathTree.Append(new GH_String(str));
                }
            }
            List <string> pathOrder = new List <string>();

            foreach (GH_String s in pathTree.AllData(false))
            {
                pathOrder.Add(s.ToString());
            }

            GH_Structure <GH_Integer> orderTree = new GH_Structure <GH_Integer>(); //a tree that the data is the order of each data, this tree is reference for sorting

            for (int i = 0; i < pathOrder.Count; i++)
            {
                string[] pathSeg;
                string   indSeg;
                GH_Path.SplitPathLikeString(pathOrder[i], out pathSeg, out indSeg);
                int[] pInd  = System.Array.ConvertAll(pathSeg, str => System.Convert.ToInt32(str));
                int   index = System.Convert.ToInt32(indSeg);
                orderTree.Insert(new GH_Integer(i), new GH_Path(pInd), index);
            }

            GH_Structure <IGH_Goo>    outGeoTree   = new GH_Structure <IGH_Goo>();
            List <IGH_Goo>            outGeoList   = new List <IGH_Goo>();
            GH_Structure <IGH_Goo>    outPathTree  = new GH_Structure <IGH_Goo>();
            List <IGH_Goo>            outPathList  = new List <IGH_Goo>();
            GH_Structure <IGH_Goo>    outIndTree   = new GH_Structure <IGH_Goo>();
            List <IGH_Goo>            outIndList   = new List <IGH_Goo>();
            GH_Structure <GH_Integer> outOrderTree = new GH_Structure <GH_Integer>();
            List <GH_Integer>         outOrderList = new List <GH_Integer>();

            for (int i = 0; i < storedPath.Count; i++)
            {
                string   p = pathOrder[System.Convert.ToInt32(storedPath[i])];
                string[] pathSeg;
                string   indSeg;

                if (GH_Path.SplitPathLikeString(p, out pathSeg, out indSeg))
                {
                    int[]   pInd  = System.Array.ConvertAll(pathSeg, str => System.Convert.ToInt32(str));
                    GH_Path path  = new GH_Path(pInd);
                    int     index = System.Convert.ToInt32(indSeg);
                    if (maintainPath)
                    {
                        outGeoTree.Append((IGH_GeometricGoo)inGeoTree.get_Branch(path)[index], path);
                        outPathTree.Append(new GH_String(path.ToString()), path);
                        outIndTree.Append(new GH_Integer(index), path);
                        outOrderTree.Append((GH_Integer)(orderTree.get_Branch(path)[index]), path);
                    }
                    else
                    {
                        outGeoList.Add((IGH_GeometricGoo)inGeoTree.get_Branch(path)[index]);
                        outPathList.Add(new GH_String(path.ToString()));
                        outIndList.Add(new GH_Integer(index));
                        outOrderList.Add((GH_Integer)orderTree.get_Branch(path)[index]);
                    }
                }
            }
            if (maintainPath)
            {
                if (this.sortByIndex)
                {
                    outGeoTree = SortTreeByIndex(outGeoTree, outOrderTree);
                    outIndTree = SortTreeByIndex(outIndTree, outOrderTree);
                }
                DA.SetDataTree(0, outGeoTree);
                DA.SetDataTree(1, outPathTree);
                DA.SetDataTree(2, outIndTree);
                DA.SetDataTree(3, outOrderTree);
            }
            else
            {
                if (this.sortByIndex)
                {
                    List <IGH_Goo> gooCopy = outGeoList;
                    outGeoList.Sort(new SelectCompareGoo(gooCopy, outOrderList));
                    gooCopy = outPathList;
                    outPathList.Sort(new SelectCompareGoo(gooCopy, outOrderList));
                    gooCopy = outIndList;
                    outIndList.Sort(new SelectCompareGoo(gooCopy, outOrderList));
                }
                DA.SetDataList(0, outGeoList);
                DA.SetDataList(1, outPathList);
                DA.SetDataList(2, outIndList);
                DA.SetDataTree(3, outOrderTree);
            }
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Curve> boundary = new List <Curve>();

            DA.GetDataList(0, boundary);

            int zoom = -1;

            DA.GetData(1, ref zoom);

            string filePath = string.Empty;

            DA.GetData(2, ref filePath);
            if (!filePath.EndsWith(@"\"))
            {
                filePath = filePath + @"\";
            }

            string prefix = string.Empty;

            DA.GetData(3, ref prefix);
            if (prefix == string.Empty)
            {
                prefix = slippySource;
            }

            string URL = slippyURL;
            //DA.GetData<string>(4, ref URL);

            string userAgent = string.Empty;

            DA.GetData(4, ref userAgent);

            bool run = false;

            DA.GetData <bool>("Run", ref run);

            GH_Structure <GH_String>    mapList  = new GH_Structure <GH_String>();
            GH_Structure <GH_Rectangle> imgFrame = new GH_Structure <GH_Rectangle>();
            GH_Structure <GH_String>    tCount   = new GH_Structure <GH_String>();


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


                ///Get image frame for given boundary and  make sure it's valid
                if (!boundary[i].GetBoundingBox(true).IsValid)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Boundary is not valid.");
                    return;
                }
                BoundingBox boundaryBox = boundary[i].GetBoundingBox(true);

                ///TODO: look into scaling boundary to get buffer tiles

                ///file path for final image
                string imgPath = filePath + prefix + "_" + i + ".jpg";

                ///location of final image file
                mapList.Append(new GH_String(imgPath), path);

                ///create cache folder for images
                string        cacheLoc       = filePath + @"HeronCache\";
                List <string> cachefilePaths = new List <string>();
                if (!Directory.Exists(cacheLoc))
                {
                    Directory.CreateDirectory(cacheLoc);
                }

                ///tile bounding box array
                List <Point3d> boxPtList = new List <Point3d>();

                ///get the tile coordinates for all tiles within boundary
                var ranges = Convert.GetTileRange(boundaryBox, zoom);
                List <List <int> > tileList = new List <List <int> >();
                var x_range = ranges.XRange;
                var y_range = ranges.YRange;

                if (x_range.Length > 100 || y_range.Length > 100)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "This tile range is too big (more than 100 tiles in the x or y direction). Check your units.");
                    return;
                }

                ///cycle through tiles to get bounding box
                for (int y = (int)y_range.Min; y <= y_range.Max; y++)
                {
                    for (int x = (int)x_range.Min; x <= x_range.Max; x++)
                    {
                        ///add bounding box of tile to list
                        boxPtList.AddRange(Convert.GetTileAsPolygon(zoom, y, x).ToList());
                        cachefilePaths.Add(cacheLoc + slippySource.Replace(" ", "") + zoom + x + y + ".jpg");
                        tileTotalCount = tileTotalCount + 1;
                    }
                }

                tCount.Insert(new GH_String(tileTotalCount + " tiles (" + tileDownloadedCount + " downloaded / " + (tileTotalCount - tileDownloadedCount) + " cached)"), path, 0);

                ///bounding box of tile boundaries
                BoundingBox bbox = new BoundingBox(boxPtList);

                var rect = BBoxToRect(bbox);
                imgFrame.Append(new GH_Rectangle(rect), path);

                AddPreviewItem(imgPath, boundary[i], rect);

                ///tile range as string for (de)serialization of TileCacheMeta
                string tileRangeString = zoom.ToString()
                                         + x_range[0].ToString()
                                         + y_range[0].ToString()
                                         + x_range[1].ToString()
                                         + y_range[1].ToString();

                ///check if the existing final image already covers the boundary.
                ///if so, no need to download more or reassemble the cached tiles.
                if ((TileCacheMeta == tileRangeString) && Convert.CheckCacheImagesExist(cachefilePaths))
                {
                    if (File.Exists(imgPath))
                    {
                        using (Bitmap imageT = new Bitmap(imgPath))
                        {
                            ///getting commments currently only working for JPG
                            ///TODO: get this to work for any image type or
                            ///find another way to check if the cached image covers the boundary.
                            string imgComment = imageT.GetCommentsFromJPG();

                            imageT.Dispose();

                            ///check to see if tilerange in comments matches current tilerange
                            if (imgComment == (slippySource.Replace(" ", "") + tileRangeString))
                            {
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Using existing image.");
                                continue;
                            }
                        }
                    }
                }



                ///Query Slippy URL
                ///download all tiles within boundary
                ///merge tiles into one bitmap
                ///API to query


                ///Do the work of assembling image
                ///setup final image container bitmap
                int    fImageW    = ((int)x_range.Length + 1) * 256;
                int    fImageH    = ((int)y_range.Length + 1) * 256;
                Bitmap finalImage = new Bitmap(fImageW, fImageH);


                int imgPosW = 0;
                int imgPosH = 0;

                if (run == true)
                {
                    using (Graphics g = Graphics.FromImage(finalImage))
                    {
                        g.Clear(Color.Black);
                        for (int y = (int)y_range.Min; y <= (int)y_range.Max; y++)
                        {
                            for (int x = (int)x_range.Min; x <= (int)x_range.Max; x++)
                            {
                                //create tileCache name
                                string tileCache    = slippySource.Replace(" ", "") + zoom + x + y + ".jpg";
                                string tileCacheLoc = cacheLoc + tileCache;

                                //check cache folder to see if tile image exists locally
                                if (File.Exists(tileCacheLoc))
                                {
                                    Bitmap tmpImage = new Bitmap(Image.FromFile(tileCacheLoc));
                                    ///add tmp image to final
                                    g.DrawImage(tmpImage, imgPosW * 256, imgPosH * 256);
                                    tmpImage.Dispose();
                                }

                                else
                                {
                                    tileList.Add(new List <int> {
                                        zoom, y, x
                                    });
                                    string urlAuth = Convert.GetZoomURL(x, y, zoom, slippyURL);

                                    System.Net.WebClient client = new System.Net.WebClient();

                                    ///insert header if required
                                    client.Headers.Add("user-agent", userAgent);

                                    client.DownloadFile(urlAuth, tileCacheLoc);
                                    Bitmap tmpImage = new Bitmap(Image.FromFile(tileCacheLoc));
                                    client.Dispose();

                                    //add tmp image to final
                                    g.DrawImage(tmpImage, imgPosW * 256, imgPosH * 256);
                                    tmpImage.Dispose();
                                    tileDownloadedCount = tileDownloadedCount + 1;
                                }

                                //increment x insert position, goes left to right
                                imgPosW++;
                            }
                            //increment y insert position, goes top to bottom
                            imgPosH++;
                            imgPosW = 0;
                        }
                        //garbage collection
                        g.Dispose();

                        //add tile range meta data to image comments
                        finalImage.AddCommentsToJPG(slippySource.Replace(" ", "") + tileRangeString);

                        //save the image
                        finalImage.Save(imgPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                    }
                }

                //garbage collection
                finalImage.Dispose();


                //add to tile count total
                tCount.Insert(new GH_String(tileTotalCount + " tiles (" + tileDownloadedCount + " downloaded / " + (tileTotalCount - tileDownloadedCount) + " cached)"), path, 0);

                //write out new tile range metadata for serialization
                TileCacheMeta = tileRangeString;
            }


            DA.SetDataTree(0, mapList);
            DA.SetDataTree(1, imgFrame);
            DA.SetDataTree(2, tCount);
            ///Add copyright info here
            DA.SetDataList(3, "");
        }
Exemple #9
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //bool inputLock = false;
            string key = "Leopard(" + this.InstanceGuid + ")";

            GH_Structure <IGH_GeometricGoo> inGeoTree;

            if (!DA.GetDataTree <IGH_GeometricGoo>(0, out inGeoTree))
            {
                return;
            }

            GH_Structure <IGH_GeometricGoo> ptsGoo = new GH_Structure <IGH_GeometricGoo>();

            for (int i = 0; i < inGeoTree.PathCount; i++)
            {
                for (int j = 0; j < inGeoTree.Branches[i].Count; j++)
                {
                    Mesh mesh;
                    if (!inGeoTree.Branches[i][j].CastTo <Mesh>(out mesh))
                    {
                        continue;
                    }
                    else
                    {
                        GH_Path    path    = inGeoTree.get_Path(i);
                        List <int> newPath = new List <int>();
                        for (int p = 0; p < path.Indices.Length; p++)
                        {
                            newPath.Add(path.Indices[p]);
                        }

                        PlanktonMesh          pMesh = mesh.ToPlanktonMesh();
                        IEnumerable <Point3d> pts   = pMesh.GetPositions();

                        foreach (Point3d p in pts)
                        {
                            if (inGeoTree.PathCount == 1)
                            {
                                ptsGoo.Append(GH_Convert.ToGeometricGoo(p), inGeoTree.get_Path(i));
                            }
                            else
                            {
                                ptsGoo.Append(GH_Convert.ToGeometricGoo(p), new GH_Path(newPath.ToArray()));
                            }
                        }
                    }
                }
            }

            //ptsGoo.Simplify(GH_SimplificationMode.CollapseLeadingOverlaps);

            //clear all stored selection
            if (resetStoredPath)
            {
                storedPath.Clear();
            }

            //delete the preview baked objects
            if (!freezePreviewObjects)
            {
                RemovePreviewObjects();
            }

            //generate the preview baked objects
            if (!inputLock && (generatePreview || !freezePreviewObjects))
            {
                GeneratePreViewObjectsI(ptsGoo);                                                          // && !freezePreviewObjects)
            }
            //happens when unlock
            //if (addSelection)
            //    SelectStoredPathObj(storedPath);


            GH_Structure <GH_String> pathTree = new GH_Structure <GH_String>(); //a tree that the data stored is its path

            for (int i = 0; i < ptsGoo.PathCount; i++)
            {
                string path = ptsGoo.Paths[i].ToString();
                for (int j = 0; j < ptsGoo.Branches[i].Count; j++)
                {
                    string str = path + "(" + j.ToString() + ")";
                    pathTree.Append(new GH_String(str));
                }
            }
            List <string> pathOrder = new List <string>();

            foreach (GH_String s in pathTree.AllData(false))
            {
                pathOrder.Add(s.ToString());
            }

            GH_Structure <GH_Integer> orderTree = new GH_Structure <GH_Integer>(); //a tree that the data is the order of each data, this tree is reference for sorting

            for (int i = 0; i < pathOrder.Count; i++)
            {
                string[] pathSeg;
                string   indSeg;
                GH_Path.SplitPathLikeString(pathOrder[i], out pathSeg, out indSeg);
                int[] pInd  = System.Array.ConvertAll(pathSeg, str => System.Convert.ToInt32(str));
                int   index = System.Convert.ToInt32(indSeg);
                orderTree.Insert(new GH_Integer(i), new GH_Path(pInd), index);
            }

            GH_Structure <IGH_Goo>    outGeoTree   = new GH_Structure <IGH_Goo>();
            GH_Structure <IGH_Goo>    outIndTree   = new GH_Structure <IGH_Goo>();
            GH_Structure <GH_Integer> outOrderTree = new GH_Structure <GH_Integer>();

            for (int i = 0; i < storedPath.Count; i++)
            {
                string   p = pathOrder[System.Convert.ToInt32(storedPath[i])];
                string[] pathSeg;
                string   indSeg;

                if (GH_Path.SplitPathLikeString(p, out pathSeg, out indSeg))
                {
                    int[]   pInd  = System.Array.ConvertAll(pathSeg, str => System.Convert.ToInt32(str));
                    GH_Path path  = new GH_Path(pInd);
                    int     index = System.Convert.ToInt32(indSeg);

                    outGeoTree.Append((IGH_GeometricGoo)ptsGoo.get_Branch(path)[index], path);
                    outIndTree.Append(new GH_Integer(index), path);
                    outOrderTree.Append((GH_Integer)(orderTree.get_Branch(path)[index]), path);
                }
            }

            if (this.sortByIndex)
            {
                outGeoTree = SortTreeByIndex(outGeoTree, outOrderTree);
                outIndTree = SortTreeByIndex(outIndTree, outOrderTree);
            }
            DA.SetDataTree(0, outGeoTree);
            DA.SetDataTree(1, outIndTree);
        }
        public static GH_Structure <IGH_Goo> DictToGHStruct(string k, Dictionary <string, dynamic> dict)
        {
            GH_Structure <IGH_Goo> ghStructure = new GH_Structure <IGH_Goo>();

            if (!(dict.Count == 0))
            {
                if (dict.TryGetValue(k, out dynamic _dataDict))
                {
                    //if value is a dictionary ..
                    if (_dataDict is Dictionary <string, dynamic> )
                    {
                        foreach (dynamic _key in _dataDict.Keys)
                        {
                            foreach (dynamic _value in _dataDict[_key])
                            {
                                if (int.TryParse(_key, out int _result))
                                {
                                    // if dictionary value is a list
                                    GH_Path p = new GH_Path(_result);
                                    if (_value is List <dynamic> )
                                    {
                                        for (int i = 0; i < _value.Count; i++)
                                        {
                                            IGH_Goo goo = null;
                                            if (goo.CastFrom(_value[i]))
                                            {
                                                ghStructure.Insert(goo, p, i);
                                            }
                                        }
                                    }
                                    // if dictionary value is a single item
                                    else
                                    {
                                        IGH_Goo goo = null;
                                        if (goo.CastFrom(_value))
                                        {
                                            ghStructure.Insert(goo, p, 0);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    /// if its a list
                    else if (_dataDict is List <dynamic> )
                    {
                        GH_Path p = new GH_Path(int.Parse(k));
                        for (int i = 0; i < _dataDict.Count; i++)
                        {
                            //if (GH_Goo.CastFrom(_dataDict[i]))
                            //    ghStructure.Insert(goo, p, i);
                        }
                    }
                    else
                    {
                        GH_Path p   = new GH_Path(int.Parse(k));
                        IGH_Goo goo = null;
                        if (goo.CastFrom(_dataDict))
                        {
                            ghStructure.Insert(goo, p, 0);
                        }
                    }
                }
            }
            return(ghStructure);
        }
Exemple #11
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            #region INPUTS
            // import silkwormSettings file
            List<string> silkwormSettings = new List<string>();
            if (!DA.GetDataList(0, silkwormSettings)) return;

            List<Brep> things = new List<Brep>();
            if (!DA.GetDataList(1, things)) return;
            // import Silkworm Movement

            SilkwormUtility sUtil = new SilkwormUtility();
            Dictionary<string, string> Settings = sUtil.convertSettings(silkwormSettings);
            SilkwormCalculator calc = new SilkwormCalculator(Settings);

            #region Optional Inputs

            int infType = 0;
            if (!DA.GetData(2, ref infType)) { }

            List<double> spacing = new List<double>();
            if (!DA.GetDataList(3, spacing)) { }

            List<double> infDens = new List<double>();
            if (!DA.GetDataList(4, infDens)) { }
            List<double> infRot = new List<double>();
            if (!DA.GetDataList(5, infRot)) { }

            #endregion

            if (spacing.Count<1)
            {
                spacing.Add(0.66);
                //TODO Calculator

            }
            if (infDens.Count < 1)
            {
                infDens.Add(double.Parse(Settings["fill_density"]));

            }
            if (infRot.Count < 1)
            {
                infRot.Add(double.Parse(Settings["fill_angle"]));

            }
            #endregion

            SilkwormSkein skein = new SilkwormSkein(Settings, things);

            //Switch depending on which infill type is selected by input
            if (infType == 0)
            {
                //Match length of data
                if (spacing.Count != things.Count)
                {
                    List<double> newspacing = new List<double>();
                    for (int e = 0; e < things.Count; e++)
                    {
                        newspacing.Add(spacing[0]);
                    }
                    spacing = newspacing;
                }

                skein.Skinner(spacing);
            }
            if (infType == 1)
            {
                //Match length of data
                if (infDens.Count != things.Count)
                {
                    List<double> newinfDens = new List<double>();
                    for (int e = 0; e < things.Count; e++)
                    {
                        newinfDens.Add(infDens[0]);
                    }
                    spacing = newinfDens;
                }
                if (infRot.Count != things.Count)
                {
                    List<double> newinfRot = new List<double>();
                    for (int e = 0; e < things.Count; e++)
                    {
                        newinfRot.Add(infRot[0]);
                    }
                    spacing = newinfRot;
                }

                skein.Filler(infDens, infRot);
            }

            //Reflect Errors and Warnings

            foreach (string message in skein.ErrorMessages)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, message);

            }
            foreach (string message in skein.WarningMessages)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, message);

            }

            //Output Holders
            List<Curve>[] plPerimeter = skein.curvePerimeter;
            List<Curve>[] plInfill = skein.curveInfill;

            GH_Structure<GH_Curve> InfillRegion = new GH_Structure<GH_Curve>();

            //Create GH_Structure
            #region Create Structure from Curves

            if (plPerimeter.Length > 0)
            {
                for (int i = 0; i < plPerimeter.Length; i++)
                {
                  if (plPerimeter[i] != null)
                        {
                    for (int j = 0; j < plPerimeter[i].Count; j++)
                    {

                            Curve aShape = plPerimeter[i][j].ToNurbsCurve();

                            GH_Curve gShapes = new GH_Curve(aShape);
                            InfillRegion.Insert(gShapes, new GH_Path(i, 0), j);
                            //}
                        }
                    }
                }
            }
            if (plInfill.Length > 0)
            {
                for (int i = 0; i < plInfill.Length; i++)
                {
            if (plInfill[i] != null)
                        {
                    for (int j = 0; j < plInfill[i].Count; j++)
                    {

                            Curve aShape = plInfill[i][j].ToNurbsCurve();

                            GH_Curve gShapes = new GH_Curve(aShape);
                            InfillRegion.Insert(gShapes, new GH_Path(i, 1), j);
                        }
                    }
                }
            }

            #endregion

            //Output
            if (!DA.SetDataTree(0, InfillRegion)) { return; }
        }
Exemple #12
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Curve> boundary = new List <Curve>();

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

            int zoom = -1;

            DA.GetData <int>(1, ref zoom);

            string folderPath = string.Empty;

            DA.GetData <string>(2, ref folderPath);
            if (!folderPath.EndsWith(@"\"))
            {
                folderPath = folderPath + @"\";
            }

            string prefix = string.Empty;

            DA.GetData <string>(3, ref prefix);
            if (prefix == "")
            {
                prefix = mbSource;
            }

            string URL = mbURL;

            ///get a valid mapbox token to send along with query
            string mbToken = string.Empty;

            DA.GetData <string>(4, ref mbToken);
            if (mbToken == "")
            {
                string hmbToken = System.Environment.GetEnvironmentVariable("HERONMAPBOXTOKEN");
                if (hmbToken != null)
                {
                    mbToken = hmbToken;
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Using Mapbox token stored in Environment Variable HERONMAPBOXTOKEN.");
                }
                else
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No Mapbox token is specified.  Please get a valid token from mapbox.com");
                    return;
                }
            }

            bool run = false;

            DA.GetData <bool>("Run", ref run);

            GH_Structure <GH_String>    mapList  = new GH_Structure <GH_String>();
            GH_Structure <GH_Rectangle> imgFrame = new GH_Structure <GH_Rectangle>();
            GH_Structure <GH_String>    tCount   = new GH_Structure <GH_String>();

            /*
             * ///Save for later development of warping
             * ///Setup for warping
             * RESTful.GdalConfiguration.ConfigureGdal();
             * RESTful.GdalConfiguration.ConfigureOgr();
             *
             * OSGeo.OSR.SpatialReference userSRS = new OSGeo.OSR.SpatialReference("");
             * userSRS.SetFromUserInput("WGS84");
             *
             * OSGeo.OSR.SpatialReference mapboxSRS = new OSGeo.OSR.SpatialReference("");
             * mapboxSRS.SetFromUserInput("EPSG:3857");
             *
             * ///Set transform from input spatial reference to Rhino spatial reference
             * OSGeo.OSR.SpatialReference rhinoSRS = new OSGeo.OSR.SpatialReference("");
             * rhinoSRS.SetWellKnownGeogCS("WGS84");
             *
             * ///This transform moves and scales the points required in going from userSRS to XYZ and vice versa
             * //Transform userSRSToModelTransform = Heron.Convert.GetUserSRSToModelTransform(userSRS);
             * Transform modelToUserSRSTransform = Heron.Convert.GetModelToUserSRSTransform(userSRS);
             * Transform mapboxSRSToModelTransform = Heron.Convert.GetUserSRSToModelTransform(mapboxSRS);
             * Transform modelToMapboxSRSTransform = Heron.Convert.GetModelToUserSRSTransform(mapboxSRS);
             */

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


                //Get image frame for given boundary and  make sure it's valid
                if (!boundary[i].GetBoundingBox(true).IsValid)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Boundary is not valid.");
                    return;
                }
                BoundingBox boundaryBox = boundary[i].GetBoundingBox(true);

                ///TODO: look into scaling boundary to get buffer tiles

                ///file path for final image
                string imgPath = folderPath + prefix + "_" + i + ".jpg";

                if (!tilesOut)
                {
                    //location of final image file
                    mapList.Append(new GH_String(imgPath), path);
                }

                //create cache folder for images
                string        cacheLoc       = folderPath + @"HeronCache\";
                List <string> cacheFilePaths = new List <string>();
                if (!Directory.Exists(cacheLoc))
                {
                    Directory.CreateDirectory(cacheLoc);
                }

                //tile bounding box array
                List <Point3d> boxPtList = new List <Point3d>();

                //get the tile coordinates for all tiles within boundary
                var ranges = Convert.GetTileRange(boundaryBox, zoom);
                List <List <int> > tileList = new List <List <int> >();
                var x_range = ranges.XRange;
                var y_range = ranges.YRange;

                if (x_range.Length > 100 || y_range.Length > 100)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "This tile range is too big (more than 100 tiles in the x or y direction). Check your units.");
                    return;
                }

                List <Rectangle3d> tileRectangles = new List <Rectangle3d>();

                //cycle through tiles to get bounding box
                for (int y = (int)y_range.Min; y <= y_range.Max; y++)
                {
                    for (int x = (int)x_range.Min; x <= x_range.Max; x++)
                    {
                        //add bounding box of tile to list
                        List <Point3d> boxPts = Convert.GetTileAsPolygon(zoom, y, x).ToList();
                        boxPtList.AddRange(boxPts);
                        string cacheFilePath = cacheLoc + mbSource.Replace(" ", "") + zoom + "-" + x + "-" + y + ".jpg";
                        cacheFilePaths.Add(cacheFilePath);

                        tileTotalCount = tileTotalCount + 1;

                        if (tilesOut)
                        {
                            mapList.Append(new GH_String(cacheFilePath), path);
                            Rectangle3d tileRectangle = BBoxToRect(new BoundingBox(boxPts));
                            tileRectangles.Add(tileRectangle);
                            imgFrame.Append(new GH_Rectangle(tileRectangle), path);
                        }
                    }
                }

                tCount.Insert(new GH_String(tileTotalCount + " tiles (" + tileDownloadedCount + " downloaded / " + (tileTotalCount - tileDownloadedCount) + " cached)"), path, 0);

                //bounding box of tile boundaries
                BoundingBox bbox = new BoundingBox(boxPtList);

                var rect = BBoxToRect(bbox);
                if (!tilesOut)
                {
                    imgFrame.Append(new GH_Rectangle(rect), path);
                }

                ///tile range as string for (de)serialization of TileCacheMeta
                string tileRangeString = zoom.ToString()
                                         + x_range[0].ToString()
                                         + y_range[0].ToString()
                                         + x_range[1].ToString()
                                         + y_range[1].ToString();

                ///check if the existing final image already covers the boundary.
                ///if so, no need to download more or reassemble the cached tiles.

                if ((TileCacheMeta == tileRangeString) && Convert.CheckCacheImagesExist(cacheFilePaths))
                {
                    if (File.Exists(imgPath) && !tilesOut)
                    {
                        using (Bitmap imageT = new Bitmap(imgPath))
                        {
                            ///getting commments currently only working for JPG
                            ///TODO: get this to work for any image type or
                            ///find another way to check if the cached image covers the boundary.
                            string imgComment = string.Empty;

                            ///Save for later development of warping
                            //if (!warped)
                            imgComment = imageT.GetCommentsFromJPG();

                            imageT.Dispose();

                            ///check to see if tilerange in comments matches current tilerange
                            if (imgComment == (mbSource.Replace(" ", "") + tileRangeString))
                            {
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Using existing image.");
                                AddPreviewItem(imgPath, boundary[i], rect);
                                continue;
                            }
                        }
                    }

                    if (tilesOut)
                    {
                        for (int t = 0; t < cacheFilePaths.Count; t++)
                        {
                            if (File.Exists(cacheFilePaths[t]))
                            {
                                AddPreviewItem(cacheFilePaths[t], tileRectangles[t].ToNurbsCurve(), tileRectangles[t]);
                            }
                        }
                        continue;
                    }
                }



                ///Query Mapbox URL
                ///download all tiles within boundary
                ///merge tiles into one bitmap
                ///API to query
                string mbURLauth = mbURL + mbToken;


                ///Do the work of assembling image
                ///setup final image container bitmap
                int    fImageW    = ((int)x_range.Length + 1) * 512;
                int    fImageH    = ((int)y_range.Length + 1) * 512;
                Bitmap finalImage = new Bitmap(fImageW, fImageH);


                int imgPosW = 0;
                int imgPosH = 0;

                /*
                 * ///Save for later development of warping
                 * List<GCP> gcpList = new List<GCP>();
                 */

                using (Graphics g = Graphics.FromImage(finalImage))
                {
                    g.Clear(Color.Black);
                    for (int y = (int)y_range.Min; y <= (int)y_range.Max; y++)
                    {
                        for (int x = (int)x_range.Min; x <= (int)x_range.Max; x++)
                        {
                            ///create tileCache name
                            string tileCache    = mbSource.Replace(" ", "") + zoom + "-" + x + "-" + y + ".jpg";
                            string tileCacheLoc = cacheLoc + tileCache;

                            /*
                             * ///Save for later development of warping
                             * ///Get GCPs for warping
                             * Point3d tileCorner = Heron.Convert.GetTileAsPolygon(zoom, y, x)[3];
                             * var tileCorner3857 = Convert.Point3dToOgrPoint(tileCorner, modelToMapboxSRSTransform);
                             * GCP gcp = new GCP(tileCorner3857.GetX(0), tileCorner3857.GetY(0), tileCorner3857.GetZ(0), imgPosW * 512, imgPosH * 512, tileCorner3857.ToString(), zoom + x + y + "");
                             * gcpList.Add(gcp);
                             */

                            ///check cache folder to see if tile image exists locally
                            if (File.Exists(tileCacheLoc))
                            {
                                Bitmap tmpImage = new Bitmap(Image.FromFile(tileCacheLoc));
                                ///add tmp image to final
                                g.DrawImage(tmpImage, imgPosW * 512, imgPosH * 512);
                                tmpImage.Dispose();
                            }

                            else
                            {
                                tileList.Add(new List <int> {
                                    zoom, y, x
                                });
                                string urlAuth = Convert.GetZoomURL(x, y, zoom, mbURLauth);

                                Bitmap tmpImage = new Bitmap(512, 512);

                                System.Net.WebClient client = new System.Net.WebClient();
                                if (run == true)
                                {
                                    try
                                    {
                                        client.DownloadFile(urlAuth, tileCacheLoc);
                                        tmpImage = new Bitmap(Image.FromFile(tileCacheLoc));
                                    }
                                    catch (WebException e)
                                    {
                                        using (Graphics tmp = Graphics.FromImage(tmpImage)) { tmp.Clear(Color.White); }
                                        AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, e.Message);
                                    }
                                }
                                client.Dispose();


                                ///add tmp image to final
                                g.DrawImage(tmpImage, imgPosW * 512, imgPosH * 512);
                                tmpImage.Dispose();
                                tileDownloadedCount = tileDownloadedCount + 1;
                            }

                            ///increment x insert position, goes left to right
                            imgPosW++;
                        }
                        ///increment y insert position, goes top to bottom
                        imgPosH++;
                        imgPosW = 0;
                    }
                    ///garbage collection
                    g.Dispose();

                    ///add tile range meta data to image comments
                    finalImage.AddCommentsToJPG(mbSource.Replace(" ", "") + tileRangeString);

                    ///Save for later development of warping
                    ///if (!warped)
                    ///save the image
                    finalImage.Save(imgPath, ImageFormat.Jpeg);
                }

                /*
                 * ///Save for later development of warping
                 * byte[] imageBuffer;
                 * string memFilename = "/vsimem/inmemfile";
                 * string memTranslated = "/vsimem/inmemfileTranslated";
                 * string memWarped = "/vsimem/inmemfileWarped";
                 * using (MemoryStream stream = new MemoryStream())
                 * {
                 *  finalImage.Save(stream, ImageFormat.Jpeg);
                 *  imageBuffer = stream.ToArray();
                 * }
                 */

                //garbage collection
                finalImage.Dispose();

                /*
                 * ///Save for later development of warping
                 * Gdal.FileFromMemBuffer(memFilename, imageBuffer);
                 * Dataset gdalImage = Gdal.Open(memFilename, Access.GA_ReadOnly);
                 * var upperLeft3857 = Convert.Point3dToOgrPoint(rect.Corner(3), modelToMapboxSRSTransform);
                 * var lowerRight3857 = Convert.Point3dToOgrPoint(rect.Corner(1), modelToMapboxSRSTransform);
                 * var upperLeft4326 = Convert.Point3dToOgrPoint(rect.Corner(3), modelToUserSRSTransform);
                 * var lowerRight4326 = Convert.Point3dToOgrPoint(rect.Corner(1), modelToUserSRSTransform);
                 * List<string> translateOptions = new List<string> { "-a_srs", "EPSG:3857",
                 *  "-r", "bilinear",
                 *  "-a_ullr", upperLeft3857.GetX(0).ToString(), upperLeft3857.GetY(0).ToString(), lowerRight3857.GetX(0).ToString(), lowerRight3857.GetY(0).ToString() };
                 * Dataset gdalTranslated = Gdal.wrapper_GDALTranslate(memTranslated, gdalImage, new GDALTranslateOptions(translateOptions.ToArray()), null, null);
                 *
                 * var wkt = gdalTranslated.GetProjection();
                 * //gdalTranslated.SetGCPs(gcpList.ToArray(), wkt);
                 *
                 * List<string> warpOptions = new List<string> { "-t_srs", "EPSG:4326",
                 *  "-r", "bilinear",
                 *  //"-multi",
                 *  //"-wo", "NUM_THREADS=6",
                 *  "-overwrite",
                 *  //"-order", "1",
                 *  //"-tps",
                 *  "-te_srs", "EPSG:3857",
                 *  "-te", upperLeft3857.GetX(0).ToString(), lowerRight3857.GetY(0).ToString(), lowerRight3857.GetX(0).ToString(), upperLeft3857.GetY(0).ToString() };
                 *
                 * ///https://github.com/OSGeo/gdal/issues/813
                 * ///https://lists.osgeo.org/pipermail/gdal-dev/2017-February/046046.html
                 * ///Odd way to go about setting source dataset in parameters for Warp is a known issue
                 *
                 * var ptr = new[] { Dataset.getCPtr(gdalTranslated).Handle };
                 * var gcHandle = GCHandle.Alloc(ptr, GCHandleType.Pinned);
                 * try
                 * {
                 *  var dss = new SWIGTYPE_p_p_GDALDatasetShadow(gcHandle.AddrOfPinnedObject(), false, null);
                 *  Dataset gdalWarped = Gdal.wrapper_GDALWarpDestName(memWarped, 1, dss, new GDALWarpAppOptions(warpOptions.ToArray()), null, null);
                 *  var driver = Gdal.GetDriverByName("JPEG");
                 *  List<string> copyOptions = new List<string> { "QUALITY=95", "COMMENT=" + mbSource.Replace(" ", "") + tileRangeString};
                 *  var copy = driver.CreateCopy(imgPath, gdalWarped, 0, copyOptions.ToArray(), null, null);
                 *  copy.Dispose();
                 *  driver.Dispose();
                 *  gdalWarped.Dispose();
                 * }
                 * finally
                 * {
                 *  if (gcHandle.IsAllocated)
                 *      gcHandle.Free();
                 * }
                 *
                 * gdalImage.Dispose();
                 * gdalTranslated.Dispose();
                 * Gdal.Unlink(memFilename);
                 * Gdal.Unlink(memTranslated);
                 * Gdal.Unlink(memWarped);
                 */

                if (!tilesOut)
                {
                    AddPreviewItem(imgPath, boundary[i], rect);
                }
                else
                {
                    for (int t = 0; t < cacheFilePaths.Count; t++)
                    {
                        if (File.Exists(cacheFilePaths[t]))
                        {
                            AddPreviewItem(cacheFilePaths[t], tileRectangles[t].ToNurbsCurve(), tileRectangles[t]);
                        }
                    }
                }

                //add to tile count total
                tCount.Insert(new GH_String(tileTotalCount + " tiles (" + tileDownloadedCount + " downloaded / " + (tileTotalCount - tileDownloadedCount) + " cached)"), path, 0);

                //write out new tile range metadata for serialization
                TileCacheMeta = tileRangeString;
            }

            List <string> mbAtts = new List <string> {
                "© Mapbox, © OpenStreetMap", "https://www.mapbox.com/about/maps/", "http://www.openstreetmap.org/copyright"
            };

            DA.SetDataTree(0, mapList);
            DA.SetDataTree(1, imgFrame);
            DA.SetDataTree(2, tCount);
            DA.SetDataList(3, mbAtts);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            #region INPUTS
            // import silkwormSettings file
            List <string> silkwormSettings = new List <string>();
            if (!DA.GetDataList(0, silkwormSettings))
            {
                return;
            }

            List <Brep> things = new List <Brep>();
            if (!DA.GetDataList(1, things))
            {
                return;
            }
            // import Silkworm Movement


            SilkwormUtility             sUtil    = new SilkwormUtility();
            Dictionary <string, string> Settings = sUtil.convertSettings(silkwormSettings);
            SilkwormCalculator          calc     = new SilkwormCalculator(Settings);

            #region Optional Inputs

            int infType = 0;
            if (!DA.GetData(2, ref infType))
            {
            }

            List <double> spacing = new List <double>();
            if (!DA.GetDataList(3, spacing))
            {
            }

            List <double> infDens = new List <double>();
            if (!DA.GetDataList(4, infDens))
            {
            }
            List <double> infRot = new List <double>();
            if (!DA.GetDataList(5, infRot))
            {
            }

            #endregion

            if (spacing.Count < 1)
            {
                spacing.Add(0.66);
                //TODO Calculator
            }
            if (infDens.Count < 1)
            {
                infDens.Add(double.Parse(Settings["fill_density"]));
            }
            if (infRot.Count < 1)
            {
                infRot.Add(double.Parse(Settings["fill_angle"]));
            }
            #endregion

            SilkwormSkein skein = new SilkwormSkein(Settings, things);

            //Switch depending on which infill type is selected by input
            if (infType == 0)
            {
                //Match length of data
                if (spacing.Count != things.Count)
                {
                    List <double> newspacing = new List <double>();
                    for (int e = 0; e < things.Count; e++)
                    {
                        newspacing.Add(spacing[0]);
                    }
                    spacing = newspacing;
                }

                skein.Skinner(spacing);
            }
            if (infType == 1)
            {
                //Match length of data
                if (infDens.Count != things.Count)
                {
                    List <double> newinfDens = new List <double>();
                    for (int e = 0; e < things.Count; e++)
                    {
                        newinfDens.Add(infDens[0]);
                    }
                    spacing = newinfDens;
                }
                if (infRot.Count != things.Count)
                {
                    List <double> newinfRot = new List <double>();
                    for (int e = 0; e < things.Count; e++)
                    {
                        newinfRot.Add(infRot[0]);
                    }
                    spacing = newinfRot;
                }


                skein.Filler(infDens, infRot);
            }

            //Reflect Errors and Warnings

            foreach (string message in skein.ErrorMessages)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, message);
            }
            foreach (string message in skein.WarningMessages)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, message);
            }

            //Output Holders
            List <Curve>[] plPerimeter = skein.curvePerimeter;
            List <Curve>[] plInfill    = skein.curveInfill;



            GH_Structure <GH_Curve> InfillRegion = new GH_Structure <GH_Curve>();

            //Create GH_Structure
            #region Create Structure from Curves

            if (plPerimeter.Length > 0)
            {
                for (int i = 0; i < plPerimeter.Length; i++)
                {
                    if (plPerimeter[i] != null)
                    {
                        for (int j = 0; j < plPerimeter[i].Count; j++)
                        {
                            Curve aShape = plPerimeter[i][j].ToNurbsCurve();


                            GH_Curve gShapes = new GH_Curve(aShape);
                            InfillRegion.Insert(gShapes, new GH_Path(i, 0), j);
                            //}
                        }
                    }
                }
            }
            if (plInfill.Length > 0)
            {
                for (int i = 0; i < plInfill.Length; i++)
                {
                    if (plInfill[i] != null)
                    {
                        for (int j = 0; j < plInfill[i].Count; j++)
                        {
                            Curve aShape = plInfill[i][j].ToNurbsCurve();

                            GH_Curve gShapes = new GH_Curve(aShape);
                            InfillRegion.Insert(gShapes, new GH_Path(i, 1), j);
                        }
                    }
                }
            }

            #endregion

            //Output
            if (!DA.SetDataTree(0, InfillRegion))
            {
                return;
            }
        }