protected override void SolveInstance(IGH_DataAccess DA)
        {
            /// <summary>
            /// This is the method that actually does the work.
            /// </summary>
            ///
            /// First, we need to retrieve all data from the input parameters.
            /// We'll start by declaring variables and assigning them starting values.
            /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>

            // datatree should be accessed through GH_structure (grasshopper.kernal.data namespace)
            GH_Structure <GH_Point> winnerTree = new GH_Structure <GH_Point>();
            GH_Structure <GH_Point> dataTree   = new GH_Structure <GH_Point>();;

            // Then we need to access the input parameters individually.
            // When data cannot be extracted from a parameter, we should abort this method.
            if (!DA.GetDataTree(0, out dataTree))
            {
                return;
            }

            // body of code

            while (dataTree.PathCount != 0)
            {
                var pointlist = dataTree.Branches[0].GetRange(0, dataTree.Branches[0].Count);
                // copy data from first branch to winner
                winnerTree.EnsurePath(dataTree.Paths[0]);
                winnerTree.AppendRange(pointlist);
                dataTree.RemovePath(dataTree.Paths[0]);
                // test other branches for inliers with winner(0), if so delete them
                for (int i = 0; i < pointlist.Count; i++)
                {
                    var pointtest = pointlist[i];
                    for (int branchj = 0; branchj < dataTree.PathCount; branchj++)
                    {
                        for (int listj = 0; listj < dataTree.Branches[branchj].Count; listj++)
                        {
                            if (((pointtest.Value.X - dataTree.get_DataItem(dataTree.Paths[branchj], listj).Value.X) < 0.001) && ((pointtest.Value.Y - dataTree.get_DataItem(dataTree.Paths[branchj], listj).Value.Y) < 0.001) && ((pointtest.Value.Z - dataTree.get_DataItem(dataTree.Paths[branchj], listj).Value.Z) < 0.001))
                            {
                                dataTree.RemovePath(dataTree.Paths[branchj]);
                            }
                        }
                    }
                }
            }

            /// run some function on the data

            //// Finally assign the output to the output parameter.
            DA.SetDataTree(0, winnerTree);
            //DA.SetDataList(1, output);
        }
Exemplo n.º 2
0
        public void Add(Point3d position, bool wrapped)
        {
            if (Count >= size)
            {
                structure.RemoveData(structure.get_FirstItem(false));
                if (structure.get_Branch(0).Count == 0)
                {
                    structure.RemovePath(new GH_Path(0));
                }
            }
            IGH_Goo pt = new GH_Point(position);

            if (wrapped)
            {
                structure.Append(pt, new GH_Path(nextPathIndex));
                nextPathIndex++;
            }
            else
            {
                structure.Append(pt, new GH_Path(nextPathIndex));
            }
        }
Exemplo n.º 3
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)
        {
            ///Gather GHA inputs
            Curve boundary = null;

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

            string osmFilePath = string.Empty;

            DA.GetData <string>("OSM Data Location", ref osmFilePath);

            //string userSRStext = "WGS84";
            //DA.GetData<string>(2, ref userSRStext);

            List <string> filterWords = new List <string>();

            DA.GetDataList <string>(2, filterWords);

            List <string> filterKeyValue = new List <string>();

            DA.GetDataList <string>(3, filterKeyValue);

            Transform xformToMetric   = new Transform(Rhino.RhinoMath.UnitScale(RhinoDoc.ActiveDoc.ModelUnitSystem, Rhino.UnitSystem.Meters));
            Transform xformFromMetric = new Transform(Rhino.RhinoMath.UnitScale(Rhino.UnitSystem.Meters, RhinoDoc.ActiveDoc.ModelUnitSystem));

            ///Declare trees
            Rectangle3d recs = new Rectangle3d();
            GH_Structure <GH_String>        fieldNames  = new GH_Structure <GH_String>();
            GH_Structure <GH_String>        fieldValues = new GH_Structure <GH_String>();
            GH_Structure <IGH_GeometricGoo> geometryGoo = new GH_Structure <IGH_GeometricGoo>();
            GH_Structure <IGH_GeometricGoo> buildingGoo = new GH_Structure <IGH_GeometricGoo>();


            Point3d max = new Point3d();
            Point3d min = new Point3d();

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

                Point3d minM = boundary.GetBoundingBox(true).Corner(false, true, true);
                min = Heron.Convert.XYZToWGS(minM);
            }

            /// get extents (why is this not part of OsmSharp?)
            System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.Load(osmFilePath);
            if (xdoc.Root.Element("bounds") != null)
            {
                double  minlat    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlat").Value);
                double  minlon    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlon").Value);
                double  maxlat    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlat").Value);
                double  maxlon    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlon").Value);
                Point3d boundsMin = Heron.Convert.WGSToXYZ(new Point3d(minlon, minlat, 0));
                Point3d boundsMax = Heron.Convert.WGSToXYZ(new Point3d(maxlon, maxlat, 0));

                recs = new Rectangle3d(Plane.WorldXY, boundsMin, boundsMax);
            }
            else
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Cannot determine the extents of the OSM file. A 'bounds' element may not be present in the file.");
            }


            using (var fileStreamSource = File.OpenRead(osmFilePath))
            {
                /// create a source.
                OsmSharp.Streams.XmlOsmStreamSource source = new OsmSharp.Streams.XmlOsmStreamSource(fileStreamSource);

                /// filter by bounding box
                OsmSharp.Streams.OsmStreamSource sourceClipped = source;
                if (clipped)
                {
                    sourceClipped = source.FilterBox((float)max.X, (float)max.Y, (float)min.X, (float)min.Y, true);
                }

                /// create a dictionary of elements
                OsmSharp.Db.Impl.MemorySnapshotDb sourceMem = new OsmSharp.Db.Impl.MemorySnapshotDb(sourceClipped);

                /// filter the source
                var filtered = from osmGeos in sourceClipped
                               where osmGeos.Tags != null
                               select osmGeos;

                if (filterWords.Any())
                {
                    filtered = from osmGeos in filtered
                               where osmGeos.Tags.ContainsAnyKey(filterWords)
                               select osmGeos;
                }

                if (filterKeyValue.Any())
                {
                    List <Tag> tags = new List <Tag>();
                    foreach (string term in filterKeyValue)
                    {
                        string[] kv  = term.Split(',');
                        Tag      tag = new Tag(kv[0], kv[1]);
                        tags.Add(tag);
                    }
                    filtered = from osmGeos in filtered
                               where osmGeos.Tags.Intersect(tags).Any()
                               select osmGeos;
                }

                source.Dispose();

                /// loop over all objects and count them.
                int nodes = 0, ways = 0, relations = 0;

                foreach (OsmSharp.OsmGeo osmGeo in filtered)
                {
                    //NODES
                    if (osmGeo.Type == OsmGeoType.Node)
                    {
                        OsmSharp.Node n         = (OsmSharp.Node)osmGeo;
                        GH_Path       nodesPath = new GH_Path(0, nodes);

                        //populate Fields and Values for each node
                        fieldNames.AppendRange(GetKeys(osmGeo), nodesPath);
                        fieldValues.AppendRange(GetValues(osmGeo), nodesPath);

                        //get geometry for node
                        Point3d nPoint = Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0));
                        geometryGoo.Append(new GH_Point(nPoint), nodesPath);

                        //increment nodes
                        nodes++;
                    }

                    ////////////////////////////////////////////////////////////
                    //WAYS
                    if (osmGeo.Type == OsmGeoType.Way)
                    {
                        OsmSharp.Way w        = (OsmSharp.Way)osmGeo;
                        GH_Path      waysPath = new GH_Path(1, ways);

                        //populate Fields and Values for each way
                        fieldNames.AppendRange(GetKeys(osmGeo), waysPath);
                        fieldValues.AppendRange(GetValues(osmGeo), waysPath);

                        //get polyline geometry for way
                        List <Point3d> wayNodes = new List <Point3d>();
                        foreach (long j in w.Nodes)
                        {
                            OsmSharp.Node n = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, j);
                            wayNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0)));
                        }

                        PolylineCurve pL = new PolylineCurve(wayNodes);
                        if (pL.IsClosed)
                        {
                            //create base surface
                            Brep[] breps = Brep.CreatePlanarBreps(pL, DocumentTolerance());
                            geometryGoo.Append(new GH_Brep(breps[0]), waysPath);
                        }
                        else
                        {
                            geometryGoo.Append(new GH_Curve(pL), waysPath);
                        }

                        //building massing
                        if (w.Tags.ContainsKey("building") || w.Tags.ContainsKey("building:part"))
                        {
                            if (pL.IsClosed)
                            {
                                CurveOrientation orient = pL.ClosedCurveOrientation(Plane.WorldXY);
                                if (orient != CurveOrientation.CounterClockwise)
                                {
                                    pL.Reverse();
                                }

                                Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo));
                                hVec.Transform(xformFromMetric);

                                Extrusion        ex      = Extrusion.Create(pL, hVec.Z, true);
                                IGH_GeometricGoo bldgGoo = GH_Convert.ToGeometricGoo(ex);
                                buildingGoo.Append(bldgGoo, waysPath);
                            }
                        }

                        //increment ways
                        ways++;
                    }
                    ///////////////////////////////////////////////////////////

                    //RELATIONS
                    if (osmGeo.Type == OsmGeoType.Relation)
                    {
                        OsmSharp.Relation r            = (OsmSharp.Relation)osmGeo;
                        GH_Path           relationPath = new GH_Path(2, relations);

                        //populate Fields and Values for each relation
                        fieldNames.AppendRange(GetKeys(osmGeo), relationPath);
                        fieldValues.AppendRange(GetValues(osmGeo), relationPath);

                        List <Curve> pLines = new List <Curve>();

                        // start members loop
                        for (int mem = 0; mem < r.Members.Length; mem++)
                        {
                            GH_Path memberPath = new GH_Path(2, relations, mem);

                            OsmSharp.RelationMember rMem    = r.Members[mem];
                            OsmSharp.OsmGeo         rMemGeo = sourceMem.Get(rMem.Type, rMem.Id);

                            if (rMemGeo != null)
                            {
                                //get geometry for node
                                if (rMemGeo.Type == OsmGeoType.Node)
                                {
                                    long          memNodeId = rMem.Id;
                                    OsmSharp.Node memN      = (OsmSharp.Node)sourceMem.Get(rMem.Type, rMem.Id);
                                    Point3d       memPoint  = Heron.Convert.WGSToXYZ(new Point3d((double)memN.Longitude, (double)memN.Latitude, 0));
                                    geometryGoo.Append(new GH_Point(memPoint), memberPath);
                                }

                                //get geometry for way
                                if (rMem.Type == OsmGeoType.Way)
                                {
                                    long memWayId = rMem.Id;

                                    OsmSharp.Way memWay = (OsmSharp.Way)rMemGeo;

                                    //get polyline geometry for way
                                    List <Point3d> memNodes = new List <Point3d>();
                                    foreach (long memNodeId in memWay.Nodes)
                                    {
                                        OsmSharp.Node memNode = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, memNodeId);
                                        memNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)memNode.Longitude, (double)memNode.Latitude, 0)));
                                    }

                                    PolylineCurve memPolyline = new PolylineCurve(memNodes);

                                    geometryGoo.Append(new GH_Curve(memPolyline.ToNurbsCurve()), memberPath);

                                    CurveOrientation orient = memPolyline.ClosedCurveOrientation(Plane.WorldXY);
                                    if (orient != CurveOrientation.CounterClockwise)
                                    {
                                        memPolyline.Reverse();
                                    }

                                    pLines.Add(memPolyline.ToNurbsCurve());
                                }

                                //get nested relations
                                if (rMem.Type == OsmGeoType.Relation)
                                {
                                    ///not sure if this is needed
                                }
                            }
                        }
                        //end members loop

                        bool allClosed = true;
                        foreach (Curve pc in pLines)
                        {
                            if (!pc.IsClosed)
                            {
                                allClosed = false;
                            }
                        }

                        if (pLines.Count > 0 && allClosed)
                        {
                            //create base surface
                            Brep[] breps = Brep.CreatePlanarBreps(pLines, DocumentTolerance());
                            geometryGoo.RemovePath(relationPath);

                            foreach (Brep b in breps)
                            {
                                geometryGoo.Append(new GH_Brep(b), relationPath);

                                //building massing
                                if (r.Tags.ContainsKey("building") || r.Tags.ContainsKey("building:part"))
                                {
                                    Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo));
                                    hVec.Transform(xformFromMetric);

                                    //create extrusion from base surface
                                    buildingGoo.Append(new GH_Brep(Brep.CreateFromOffsetFace(b.Faces[0], hVec.Z, DocumentTolerance(), false, true)), relationPath);
                                }
                            }
                        }

                        //increment relations
                        relations++;
                    } ///end relation loop
                }     ///end filtered loop
            }         ///end osm source loop

            if (recs.IsValid)
            {
                DA.SetData(0, recs);
            }
            DA.SetDataTree(1, fieldNames);
            DA.SetDataTree(2, fieldValues);
            DA.SetDataTree(3, geometryGoo);
            DA.SetDataTree(4, buildingGoo);
        } ///end SolveInstance
Exemplo n.º 4
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Curve> boundary = new List <Curve>();

            DA.GetDataList <Curve>("Boundary", boundary);

            int Res = -1;

            DA.GetData <int>("Resolution", ref Res);

            string folderPath = string.Empty;

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

            string prefix = string.Empty;

            DA.GetData <string>("Prefix", ref prefix);

            string URL = string.Empty;

            DA.GetData <string>("REST URL", ref URL);
            if (URL.EndsWith(@"/"))
            {
                URL = URL + "export?";
            }

            bool run = false;

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

            string userSRStext = string.Empty;

            DA.GetData <string>("User Spatial Reference System", ref userSRStext);

            string imageType = string.Empty;

            DA.GetData <string>("Image Type", ref imageType);

            ///GDAL setup
            RESTful.GdalConfiguration.ConfigureOgr();

            ///TODO: implement SetCRS here.
            ///Option to set CRS here to user-defined.  Needs a SetCRS global variable.
            //string userSRStext = "EPSG:4326";

            OSGeo.OSR.SpatialReference userSRS = new OSGeo.OSR.SpatialReference("");
            userSRS.SetFromUserInput(userSRStext);
            int userSRSInt = Int16.Parse(userSRS.GetAuthorityCode(null));

            ///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);


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

            FileInfo file = new FileInfo(folderPath);

            file.Directory.Create();

            string size = string.Empty;

            if (Res != 0)
            {
                size = "&size=" + Res + "%2C" + Res;
            }

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

                ///Get image frame for given boundary
                BoundingBox imageBox = boundary[i].GetBoundingBox(false);
                imageBox.Transform(modelToUserSRSTransform);

                ///Make sure to have a rect for output
                Rectangle3d rect = BBoxToRect(imageBox);

                ///Query the REST service
                string restquery = URL +
                                   ///legacy method for creating bounding box string
                                   "bbox=" + imageBox.Min.X + "%2C" + imageBox.Min.Y + "%2C" + imageBox.Max.X + "%2C" + imageBox.Max.Y +
                                   "&bboxSR=" + userSRSInt +
                                   size +                     //"&layers=&layerdefs=" +
                                   "&imageSR=" + userSRSInt + //"&transparent=false&dpi=&time=&layerTimeOptions=" +
                                   "&format=" + imageType;    // +
                //"&f=json";
                string restqueryJSON  = restquery + "&f=json";
                string restqueryImage = restquery + "&f=image";

                mapquery.Append(new GH_String(restqueryImage), path);

                string result = string.Empty;

                ///Get extent of image from arcgis rest service as JSON
                result = Heron.Convert.HttpToJson(restqueryJSON);
                JObject jObj = JsonConvert.DeserializeObject <JObject>(result);
                if (!jObj.ContainsKey("href"))
                {
                    restqueryJSON  = restqueryJSON.Replace("export?", "exportImage?");
                    restqueryImage = restqueryImage.Replace("export?", "exportImage?");
                    mapquery.RemovePath(path);
                    mapquery.Append(new GH_String(restqueryImage), path);
                    result = Heron.Convert.HttpToJson(restqueryJSON);
                    jObj   = JsonConvert.DeserializeObject <JObject>(result);
                }

                if (run)
                {
                    Point3d extMin = new Point3d((double)jObj["extent"]["xmin"], (double)jObj["extent"]["ymin"], 0);
                    Point3d extMax = new Point3d((double)jObj["extent"]["xmax"], (double)jObj["extent"]["ymax"], 0);
                    rect = new Rectangle3d(Plane.WorldXY, extMin, extMax);
                    rect.Transform(userSRSToModelTransform);

                    ///Download image from source
                    ///Catch if JSON query throws an error
                    string imageQueryJSON = jObj["href"].ToString();
                    using (WebClient webC = new WebClient())
                    {
                        try
                        {
                            if (!String.IsNullOrEmpty(imageQueryJSON))
                            {
                                webC.DownloadFile(imageQueryJSON, folderPath + prefix + "_" + i + "." + imageType);
                                webC.Dispose();
                            }
                            else
                            {
                                webC.DownloadFile(restqueryImage, folderPath + prefix + "_" + i + "." + imageType);
                                webC.Dispose();
                            }
                        }
                        catch (WebException e)
                        {
                            AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, e.Message);
                            webC.DownloadFile(restqueryImage, folderPath + prefix + "_" + i + "." + imageType);
                            webC.Dispose();
                        }
                    }
                }
                var bitmapPath = folderPath + prefix + "_" + i + "." + imageType;
                mapList.Append(new GH_String(bitmapPath), path);

                imgFrame.Append(new GH_Rectangle(rect), path);
                AddPreviewItem(bitmapPath, rect);
            }

            DA.SetDataTree(0, mapList);
            DA.SetDataTree(1, imgFrame);
            DA.SetDataTree(2, mapquery);
        }
Exemplo n.º 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)
        {
            ///Gather GHA inputs
            Curve boundary = null;

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

            string osmFilePath = string.Empty;

            DA.GetData <string>("OSM Data Location", ref osmFilePath);

            //string userSRStext = "WGS84";
            //DA.GetData<string>(2, ref userSRStext);

            List <string> filterWords = new List <string>();

            DA.GetDataList <string>(2, filterWords);

            List <string> filterKeyValue = new List <string>();

            DA.GetDataList <string>(3, filterKeyValue);

            Transform xformToMetric   = new Transform(scaleToMetric);
            Transform xformFromMetric = new Transform(scaleFromMetric);

            ///Declare trees
            Rectangle3d recs = new Rectangle3d();
            GH_Structure <GH_String>        fieldNames  = new GH_Structure <GH_String>();
            GH_Structure <GH_String>        fieldValues = new GH_Structure <GH_String>();
            GH_Structure <IGH_GeometricGoo> geometryGoo = new GH_Structure <IGH_GeometricGoo>();
            GH_Structure <IGH_GeometricGoo> buildingGoo = new GH_Structure <IGH_GeometricGoo>();


            Point3d max = new Point3d();
            Point3d min = new Point3d();

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

                Point3d minM = boundary.GetBoundingBox(true).Corner(false, true, true);
                min = Heron.Convert.XYZToWGS(minM);
            }

            /// get extents (why is this not part of OsmSharp?)
            System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.Load(osmFilePath);
            if (xdoc.Root.Element("bounds") != null)
            {
                double  minlat    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlat").Value);
                double  minlon    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("minlon").Value);
                double  maxlat    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlat").Value);
                double  maxlon    = System.Convert.ToDouble(xdoc.Root.Element("bounds").Attribute("maxlon").Value);
                Point3d boundsMin = Heron.Convert.WGSToXYZ(new Point3d(minlon, minlat, 0));
                Point3d boundsMax = Heron.Convert.WGSToXYZ(new Point3d(maxlon, maxlat, 0));

                recs = new Rectangle3d(Plane.WorldXY, boundsMin, boundsMax);
            }
            else
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Cannot determine the extents of the OSM file. A 'bounds' element may not be present in the file. " +
                                  "Try turning off clipping in this component's menu.");
            }


            using (var fileStreamSource = File.OpenRead(osmFilePath))
            {
                /// create a source.
                OsmSharp.Streams.XmlOsmStreamSource source = new OsmSharp.Streams.XmlOsmStreamSource(fileStreamSource);

                /// filter by bounding box
                OsmSharp.Streams.OsmStreamSource sourceClipped = source;
                if (clipped)
                {
                    sourceClipped = source.FilterBox((float)max.X, (float)max.Y, (float)min.X, (float)min.Y, true);
                }

                /// create a dictionary of elements
                OsmSharp.Db.Impl.MemorySnapshotDb sourceMem = new OsmSharp.Db.Impl.MemorySnapshotDb(sourceClipped);

                /// filter the source
                var filtered = from osmGeos in sourceClipped
                               where osmGeos.Tags != null
                               select osmGeos;

                if (filterWords.Any())
                {
                    filtered = from osmGeos in filtered
                               where osmGeos.Tags.ContainsAnyKey(filterWords)
                               select osmGeos;
                }

                if (filterKeyValue.Any())
                {
                    List <Tag> tags = new List <Tag>();
                    foreach (string term in filterKeyValue)
                    {
                        string[] kv  = term.Split(',');
                        Tag      tag = new Tag(kv[0], kv[1]);
                        tags.Add(tag);
                    }
                    filtered = from osmGeos in filtered
                               where osmGeos.Tags.Intersect(tags).Any()
                               select osmGeos;
                }

                source.Dispose();

                /// loop over all objects and count them.
                int nodes = 0, ways = 0, relations = 0;
                Dictionary <PolylineCurve, GH_Path> bldgOutlines = new Dictionary <PolylineCurve, GH_Path>();
                List <BuildingPart> buildingParts = new List <BuildingPart>();


                foreach (OsmSharp.OsmGeo osmGeo in filtered)
                {
                    //NODES
                    if (osmGeo.Type == OsmGeoType.Node)
                    {
                        OsmSharp.Node n         = (OsmSharp.Node)osmGeo;
                        GH_Path       nodesPath = new GH_Path(0, nodes);

                        //populate Fields and Values for each node
                        fieldNames.AppendRange(GetKeys(osmGeo), nodesPath);
                        fieldValues.AppendRange(GetValues(osmGeo), nodesPath);

                        //get geometry for node
                        Point3d nPoint = Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0));
                        geometryGoo.Append(new GH_Point(nPoint), nodesPath);

                        //increment nodes
                        nodes++;
                    }

                    ////////////////////////////////////////////////////////////
                    //WAYS
                    if (osmGeo.Type == OsmGeoType.Way)
                    {
                        OsmSharp.Way w        = (OsmSharp.Way)osmGeo;
                        GH_Path      waysPath = new GH_Path(1, ways);

                        //populate Fields and Values for each way
                        fieldNames.AppendRange(GetKeys(osmGeo), waysPath);
                        fieldValues.AppendRange(GetValues(osmGeo), waysPath);

                        //get polyline geometry for way
                        List <Point3d> wayNodes = new List <Point3d>();
                        foreach (long j in w.Nodes)
                        {
                            OsmSharp.Node n = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, j);
                            wayNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)n.Longitude, (double)n.Latitude, 0)));
                        }

                        PolylineCurve pL = new PolylineCurve(wayNodes);
                        if (pL.IsClosed)
                        {
                            //create base surface
                            Brep[] breps = Brep.CreatePlanarBreps(pL, DocumentTolerance());
                            geometryGoo.Append(new GH_Brep(breps[0]), waysPath);
                        }
                        else
                        {
                            geometryGoo.Append(new GH_Curve(pL), waysPath);
                        }

                        //building massing
                        if ((w.Tags.ContainsKey("building") || w.Tags.ContainsKey("building:part")))// && !w.Tags.ContainsKey("construction"))
                        {
                            if (pL.IsClosed)
                            {
                                ///Populate dictionary for sorting building parts later
                                if (w.Tags.ContainsKey("building"))
                                {
                                    bldgOutlines.Add(pL, waysPath);
                                }

                                CurveOrientation orient = pL.ClosedCurveOrientation(Plane.WorldXY);
                                if (orient != CurveOrientation.CounterClockwise)
                                {
                                    pL.Reverse();
                                }

                                ///Move polylines to min height
                                double   minHeightWay = GetMinBldgHeight(osmGeo);
                                Vector3d minVec       = new Vector3d(0, 0, minHeightWay);
                                //minVec.Transform(xformFromMetric);
                                if (minHeightWay > 0.0)
                                {
                                    var minHeightTranslate = Transform.Translation(minVec);
                                    pL.Transform(minHeightTranslate);
                                }

                                Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo) - minHeightWay);
                                //hVec.Transform(xformFromMetric);

                                Extrusion        ex      = Extrusion.Create(pL, hVec.Z, true);
                                IGH_GeometricGoo bldgGoo = GH_Convert.ToGeometricGoo(ex);

                                ///Save building parts for sorting later and remove part from geometry goo tree
                                if (w.Tags.ContainsKey("building:part"))
                                {
                                    BuildingPart bldgPart = new BuildingPart(pL, bldgGoo, fieldNames[waysPath], fieldValues[waysPath], osmGeo);
                                    buildingParts.Add(bldgPart);
                                    fieldNames.RemovePath(waysPath);
                                    fieldValues.RemovePath(waysPath);
                                    geometryGoo.RemovePath(waysPath);
                                    ways = ways - 1;
                                }
                                else
                                {
                                    buildingGoo.Append(bldgGoo, waysPath);
                                }
                            }
                        }

                        //increment ways
                        ways++;
                    }
                    ///////////////////////////////////////////////////////////

                    //RELATIONS
                    if (osmGeo.Type == OsmGeoType.Relation)
                    {
                        OsmSharp.Relation r            = (OsmSharp.Relation)osmGeo;
                        GH_Path           relationPath = new GH_Path(2, relations);

                        //populate Fields and Values for each relation
                        fieldNames.AppendRange(GetKeys(osmGeo), relationPath);
                        fieldValues.AppendRange(GetValues(osmGeo), relationPath);

                        List <Curve> pLines = new List <Curve>();

                        // start members loop
                        for (int mem = 0; mem < r.Members.Length; mem++)
                        {
                            GH_Path memberPath = new GH_Path(2, relations, mem);

                            OsmSharp.RelationMember rMem    = r.Members[mem];
                            OsmSharp.OsmGeo         rMemGeo = sourceMem.Get(rMem.Type, rMem.Id);

                            if (rMemGeo != null)
                            {
                                //get geometry for node
                                if (rMemGeo.Type == OsmGeoType.Node)
                                {
                                    long          memNodeId = rMem.Id;
                                    OsmSharp.Node memN      = (OsmSharp.Node)sourceMem.Get(rMem.Type, rMem.Id);
                                    Point3d       memPoint  = Heron.Convert.WGSToXYZ(new Point3d((double)memN.Longitude, (double)memN.Latitude, 0));
                                    geometryGoo.Append(new GH_Point(memPoint), memberPath);
                                }

                                //get geometry for way
                                if (rMem.Type == OsmGeoType.Way)
                                {
                                    long memWayId = rMem.Id;

                                    OsmSharp.Way memWay = (OsmSharp.Way)rMemGeo;

                                    //get polyline geometry for way
                                    List <Point3d> memNodes = new List <Point3d>();
                                    foreach (long memNodeId in memWay.Nodes)
                                    {
                                        OsmSharp.Node memNode = (OsmSharp.Node)sourceMem.Get(OsmGeoType.Node, memNodeId);
                                        memNodes.Add(Heron.Convert.WGSToXYZ(new Point3d((double)memNode.Longitude, (double)memNode.Latitude, 0)));
                                    }

                                    PolylineCurve memPolyline = new PolylineCurve(memNodes);

                                    geometryGoo.Append(new GH_Curve(memPolyline.ToNurbsCurve()), memberPath);

                                    CurveOrientation orient = memPolyline.ClosedCurveOrientation(Plane.WorldXY);
                                    if (orient != CurveOrientation.CounterClockwise)
                                    {
                                        memPolyline.Reverse();
                                    }

                                    pLines.Add(memPolyline.ToNurbsCurve());
                                }

                                //get nested relations
                                if (rMem.Type == OsmGeoType.Relation)
                                {
                                    ///not sure if this is needed
                                }
                            }
                        }
                        //end members loop

                        bool allClosed = true;
                        foreach (Curve pc in pLines)
                        {
                            if (!pc.IsClosed)
                            {
                                allClosed = false;
                            }
                        }

                        if (pLines.Count > 0 && allClosed)
                        {
                            ///Move polylines to min height
                            double minHeight = GetMinBldgHeight(osmGeo);
                            if (minHeight > 0.0)
                            {
                                Vector3d minVec = new Vector3d(0, 0, minHeight);
                                //minVec.Transform(xformFromMetric);
                                var minHeightTranslate = Transform.Translation(minVec);
                                for (int i = 0; i < pLines.Count; i++)
                                {
                                    pLines[i].Transform(minHeightTranslate);
                                }
                            }
                            ///Create base surface
                            Brep[] breps = Brep.CreatePlanarBreps(pLines, DocumentTolerance());
                            geometryGoo.RemovePath(relationPath);

                            foreach (Brep b in breps)
                            {
                                geometryGoo.Append(new GH_Brep(b), relationPath);

                                ///Building massing
                                if (r.Tags.ContainsKey("building") || r.Tags.ContainsKey("building:part"))
                                {
                                    Vector3d hVec = new Vector3d(0, 0, GetBldgHeight(osmGeo) - minHeight);
                                    //hVec.Transform(xformFromMetric);

                                    ///Create extrusion from base surface
                                    buildingGoo.Append(new GH_Brep(Brep.CreateFromOffsetFace(b.Faces[0], hVec.Z, DocumentTolerance(), false, true)), relationPath);
                                }
                            }
                        }

                        ///Increment relations
                        relations++;
                    } ///End relation loop
                }     ///End filtered loop

                ///Add building parts to sub-branches under main building
                for (int partIndex = 0; partIndex < buildingParts.Count; partIndex++)
                {
                    BuildingPart bldgPart  = buildingParts[partIndex];
                    Point3d      partPoint = bldgPart.PartFootprint.PointAtStart;
                    partPoint.Z = 0;
                    bool          replaceBuidingMass   = false;
                    GH_Path       mainBuildingMassPath = new GH_Path();
                    PolylineCurve massOutline          = new PolylineCurve();

                    bool isRoof = bldgPart.PartOsmGeo.Tags.TryGetValue("roof:shape", out string isRoofString);
                    if (isRoof)
                    {
                        bldgPart.PartGoo = BldgPartToRoof(bldgPart);
                    }

                    foreach (KeyValuePair <PolylineCurve, GH_Path> pair in bldgOutlines)
                    {
                        PointContainment pc = pair.Key.Contains(partPoint, Plane.WorldXY, DocumentTolerance());
                        if (pc != PointContainment.Outside)
                        {
                            ///Create new sub-branch
                            int     numSubBranches = 0;
                            GH_Path partPath       = pair.Value.AppendElement(numSubBranches);
                            while (buildingGoo.PathExists(partPath))
                            {
                                numSubBranches++;
                                partPath = pair.Value.AppendElement(numSubBranches);
                            }

                            ///Add data to sub-branch
                            fieldNames.AppendRange(bldgPart.PartFieldNames, partPath);
                            fieldValues.AppendRange(bldgPart.PartFieldValues, partPath);
                            buildingGoo.Append(bldgPart.PartGoo, partPath);

                            ///Remove the main building mass
                            replaceBuidingMass   = true;
                            mainBuildingMassPath = pair.Value;
                            massOutline          = pair.Key;
                        }
                    }
                    ///Remove the main building mass
                    if (replaceBuidingMass)
                    {
                        buildingGoo.RemovePath(mainBuildingMassPath);
                        buildingGoo.Append(new GH_Curve(massOutline), mainBuildingMassPath);
                    }
                    else
                    {
                        GH_Path extrasPath = new GH_Path(3, partIndex);
                        buildingGoo.Append(bldgPart.PartGoo, extrasPath);
                        fieldNames.AppendRange(bldgPart.PartFieldNames, extrasPath);
                        fieldValues.AppendRange(bldgPart.PartFieldValues, extrasPath);
                    }
                }
            } ///end osm source loop

            if (recs.IsValid)
            {
                DA.SetData(0, recs);
            }
            DA.SetDataTree(1, fieldNames);
            DA.SetDataTree(2, fieldValues);
            DA.SetDataTree(3, geometryGoo);
            DA.SetDataTree(4, buildingGoo);
        } ///end SolveInstance