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