diff --git a/Components/API/GH_HTTPGetRequestAsync.cs b/Components/API/GH_HTTPGetRequestAsync.cs new file mode 100644 index 0000000..cc5797f --- /dev/null +++ b/Components/API/GH_HTTPGetRequestAsync.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; + +using Grasshopper.Kernel; +using Rhino.Geometry; +using System.IO; +using System.Net; +using System.Threading.Tasks; +using Formicae.Helpers.API; +using Formicae.Templates; + +namespace Formicae.Components.API +{ + public class MyComponent1 : GH_Component_HTTPAsync + { + /// + /// Initializes a new instance of the MyComponent1 class. + /// + public MyComponent1() + : base("HTTP GET (Async)", "GET Async", + "A generic HTTP GET request (asynchronous)", + Config.FormicaeTab, Config.Tabs.API) + { + } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams(GH_InputParamManager pManager) + {// active + pManager.AddBooleanParameter("Send", "S", "Perform the request?", GH_ParamAccess.item, false); + // url (endpoint) + pManager.AddTextParameter("Url", "U", "Url for the request", GH_ParamAccess.item); + + // custom headers (future) + // custom headers would be nice here: how to handle key-value pairs in GH? takes in a tree? + + // auth + int authId = pManager.AddTextParameter("Authorization", "A", "If this request requires authorization, input your formatted token as an Auth string, e.g. \"Bearer h1g23g1fdg3d1\"", GH_ParamAccess.item); + // timeout + pManager.AddIntegerParameter("Timeout", "T", "Timeout for the request in ms. If the request takes longer that this, it will fail.", GH_ParamAccess.item, 10000); + + pManager[authId].Optional = true; + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams(GH_OutputParamManager pManager) + { + pManager.AddTextParameter("Response", "R", "Request response", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance(IGH_DataAccess DA) + { + if (_shouldExpire) + { + switch (_currentState) + { + case RequestState.Off: + Message = "Inactive"; + _currentState = RequestState.Idle; + break; + + case RequestState.Error: + Message = "ERROR"; + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, _response); + _currentState = RequestState.Idle; + break; + + case RequestState.Done: + Message = "Complete!"; + _currentState = RequestState.Idle; + break; + } + // Output... + DA.SetData(0, _response); + _shouldExpire = false; + return; + } + + bool active = false; + string url = ""; + string authToken = ""; + int timeout = 0; + + DA.GetData("Send", ref active); + if (!active) + { + _currentState = RequestState.Off; + _shouldExpire = true; + _response = ""; + ExpireSolution(true); + return; + } + + if (!DA.GetData("Url", ref url)) return; + DA.GetData("Authorization", ref authToken); + if (!DA.GetData("Timeout", ref timeout)) return; + + // Validity checks + if (url == null || url.Length == 0) + { + _response = "Empty URL"; + _currentState = RequestState.Error; + _shouldExpire = true; + ExpireSolution(true); + return; + } + + _currentState = RequestState.Requesting; + Message = "Requesting..."; + + GETAsync(url, authToken, timeout); + } + + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon + { + get + { + //You can add image files to your project resources and access them like this: + // return Resources.IconForThisComponent; + return null; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid + { + get { return new Guid("5FAB55FB-06C1-4F8D-AC13-4A95BC79727F"); } + } + } +} \ No newline at end of file diff --git a/api/auth.cs b/Components/API/GH_auth.cs similarity index 84% rename from api/auth.cs rename to Components/API/GH_auth.cs index c5c88cf..cf13fb3 100644 --- a/api/auth.cs +++ b/Components/API/GH_auth.cs @@ -3,29 +3,30 @@ using Newtonsoft.Json.Linq; using Grasshopper.Kernel; using System.Threading.Tasks; -namespace Formicae.api +using Formicae.Helpers.API; +namespace Formicae.Components.API { - public class auth : GH_Component + public class GH_auth : GH_Component { /// /// Initializes a new instance of the MyComponent1 class. /// - public auth() + public GH_auth() : base("auth", "auth", "auth", - "Formicae", "api") + Config.FormicaeTab, Config.Tabs.API) { } /// /// Registers all the input parameters for this component. /// - protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) + protected override void RegisterInputParams(GH_InputParamManager pManager) { pManager.AddBooleanParameter("Trigger", "T", "Set to true to start the authentication process.", GH_ParamAccess.item); } - protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) + protected override void RegisterOutputParams(GH_OutputParamManager pManager) { pManager.AddTextParameter("AccessToken", "Token", "The OAuth access token.", GH_ParamAccess.item); } @@ -58,7 +59,7 @@ protected override void SolveInstance(IGH_DataAccess DA) { Rhino.RhinoApp.InvokeOnUiThread((Action)(() => { - this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Error during authentication: " + ex.Message); + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Error during authentication: " + ex.Message); })); } }); diff --git a/Components/DataVisualization/showWindRose.cs b/Components/DataVisualization/showWindRose.cs new file mode 100644 index 0000000..bcc7186 --- /dev/null +++ b/Components/DataVisualization/showWindRose.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; + +using Grasshopper.Kernel; +using Rhino.Geometry; + +using System.Drawing; +using Newtonsoft.Json; +namespace Formicae.Components.DataVisualization +{ + public class showWindRose : GH_Component + { + public override Guid ComponentGuid => new Guid("A45FC4A2-0E1C-415C-86D7-D29D21AD74E1"); + protected override Bitmap Icon => null; + public showWindRose() + : base("showWindRose", "showWindRose", + "showWindRose", + Config.FormicaeTab, Config.Tabs.Show) + { + } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) + { + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) + { + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance(IGH_DataAccess DA) + { + } + + } +} \ No newline at end of file diff --git a/Components/GH_CreateHeightMaps.cs b/Components/GH_CreateHeightMaps.cs deleted file mode 100644 index e6fb25b..0000000 --- a/Components/GH_CreateHeightMaps.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using Formicae.Types; -using Grasshopper.Kernel; -using Rhino.Geometry; - -namespace Formicae.Components -{ - public class GH_CreateHeightMaps : GH_Component - { - /// - /// Initializes a new instance of the GH_CreateHeightMaps class. - /// - public GH_CreateHeightMaps() - : base("GH_CreateHeightMaps", "Nickname", - "Description", - "Formicae", "Setup") - - { - } - - /// - /// Registers all the input parameters for this component. - /// - protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) - { - pManager.AddGenericParameter("WindSimModel", "WindSimModel", "WindSimModel", GH_ParamAccess.item); - } - - /// - /// Registers all the output parameters for this component. - /// - protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) - { - pManager.AddNumberParameter("HeightsMapWithoutBuildings", "HeightsMapWithoutBuildings", "HeightsMapWithoutBuildings", GH_ParamAccess.list); - pManager.AddNumberParameter("HeightsMapWithBuildings", "HeightsMapWithBuildings", "HeightsMapWithBuildings", GH_ParamAccess.list); - } - - /// - /// This is the method that actually does the work. - /// - /// The DA object is used to retrieve from inputs and store in outputs. - protected override void SolveInstance(IGH_DataAccess DA) - { - WindSimulationModel windSimModel = new WindSimulationModel(); - DA.GetData(0,ref windSimModel); - - HeightMap heightMap = new HeightMap(windSimModel); - - //var mappedWithoutBuildings = HeightMap.MapToDomain(heightMap.HeightMapWithoutBuildings(), 0, 255); - //var mappedWithBuildings = HeightMap.MapToDomain(heightMap.HeightMapWithBuildings(), 0, 255); - - var mappedWithoutBuildings = heightMap.HeightMapWithoutBuildings(); - var mappedWithBuildings = heightMap.HeightMapWithBuildings(); - - //DA.SetDataList(0,heightMap.HeightMapWithoutBuildings()); - //DA.SetDataList(1,heightMap.HeightMapWithBuildings()); - - - DA.SetDataList(0, mappedWithoutBuildings); - DA.SetDataList(1, mappedWithBuildings); - - } - - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get - { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return null; - } - } - - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid - { - get { return new Guid("0B9A9778-22FA-49AA-9C3E-730022BB56AD"); } - } - } -} \ No newline at end of file diff --git a/Components/GH_CreateSimulationBox.cs b/Components/GH_CreateSimulationBox.cs deleted file mode 100644 index bbb9b79..0000000 --- a/Components/GH_CreateSimulationBox.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using Formicae.Types; -using Grasshopper.Kernel; -using Rhino.Geometry; - -namespace Formicae.Components -{ - public class GH_CreateSimulationBox : GH_Component - { - /// - /// Initializes a new instance of the GH_CreateSimulationBox class. - /// - public GH_CreateSimulationBox() - : base("Create Simulation Box ", "Nickname", - "Description", - "Formicae", "Setup") - { - } - - /// - /// Registers all the input parameters for this component. - /// - protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) - { - pManager.AddBrepParameter("Box", "box", "500X500 box to make the simulaiton Grids", GH_ParamAccess.item); - } - - /// - /// Registers all the output parameters for this component. - /// - protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) - { - // pManager.AddMeshParameter("SimulaitonMeshGrid", "SMG", "A grid to simulate on", GH_ParamAccess.item); - pManager.AddPointParameter("SimulationPoints", "Simpts", "A grid of points to get the height maps", GH_ParamAccess.list); - pManager.AddMeshParameter("ResultMeshGrid", "RMG", "A grid to viz the results",GH_ParamAccess.item); - pManager.AddGenericParameter("SimulationBox", "simBox", "Simulation box object", GH_ParamAccess.item); - } - - /// - /// This is the method that actually does the work. - /// - /// The DA object is used to retrieve from inputs and store in outputs. - protected override void SolveInstance(IGH_DataAccess DA) - { - Brep box = new Brep(); - DA.GetData(0, ref box); - - SimulationBox simbox = new SimulationBox(box); - //var simMesh = simbox.GetSimulationMesh(); - //var simPts = simbox.GetSimulationPoints(); - //var ResultMesh = simbox.GetResultMeshGrid(); - - var simPts = simbox.LiftedPts; - var ResultMesh = simbox.LiftedResultMesh; - DA.SetDataList(0, simPts); - DA.SetData(1, ResultMesh); - DA.SetData(2, simbox); - - } - - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get - { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return null; - } - } - - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid - { - get { return new Guid("1F1E5EE5-6DD9-436C-9C7B-4D51AD92B912"); } - } - } -} \ No newline at end of file diff --git a/Components/GH_CreateWindSimulationModel.cs b/Components/GH_CreateWindSimulationModel.cs deleted file mode 100644 index 069f760..0000000 --- a/Components/GH_CreateWindSimulationModel.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using Formicae.Types; -using Grasshopper.Kernel; -using Rhino.Geometry; - -namespace Formicae.Components -{ - public class GH_CreateWindSimulationModel : GH_Component - { - /// - /// Initializes a new instance of the GH_CreateWindSimulationModel class. - /// - public GH_CreateWindSimulationModel() - : base("GH_CreateWindSimulationModel", "Nickname", - "Description", - "Formicae", "Setup") - { - } - - /// - /// Registers all the input parameters for this component. - /// - protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) - { - pManager.AddMeshParameter("TerrainMesh", "TM", "Mesh used to represent the terrain", GH_ParamAccess.item); - pManager.AddBrepParameter("Buildings Breps", "BB", "Buildings as Breps (Kepp at volumetric level and simple boxes)", GH_ParamAccess.list); - pManager.AddGenericParameter("Simulation Box", "SimBox", "Simulation Box Object", GH_ParamAccess.item); - - } - - /// - /// Registers all the output parameters for this component. - /// - protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) - { - pManager.AddGenericParameter("WindSimModel", "WindSimModel", "WindSimModel",GH_ParamAccess.item); - // pManager.AddGenericParameter("Debug", "Debug", "Debug", GH_ParamAccess.item); - } - - /// - /// This is the method that actually does the work. - /// - /// The DA object is used to retrieve from inputs and store in outputs. - protected override void SolveInstance(IGH_DataAccess DA) - { - Mesh tMesh = new Mesh(); - DA.GetData(0, ref tMesh); - Terrain terrain = new Terrain(tMesh); - - List blgsBrep = new List(); - DA.GetDataList(1, blgsBrep); - Buildings bldgs = new Buildings(blgsBrep); - - SimulationBox simBox = new SimulationBox(); - DA.GetData(2, ref simBox); - - WindSimulationModel windSimModel = new WindSimulationModel(bldgs, terrain, simBox); - - DA.SetData(0, windSimModel); - //DA.SetData(1, simBox); - - } - - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get - { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return null; - } - } - - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid - { - get { return new Guid("7C2E1E1E-CAB8-47B0-956B-9351A3BDB8BD"); } - } - } -} \ No newline at end of file diff --git a/Components/GH_postArray.cs b/Components/GH_postArray.cs new file mode 100644 index 0000000..69cba6c --- /dev/null +++ b/Components/GH_postArray.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +using Grasshopper.Kernel; +using Rhino.Geometry; +using System.Drawing; +using Newtonsoft.Json; + +namespace Formicae.Components +{ + + public class GH_postArray : GH_Component + { + public override Guid ComponentGuid => new Guid("05AACC05-6188-4760-BB01-796D6DF98607"); + protected override Bitmap Icon => null; + + public GH_postArray() + : base("GH_postArray", "GH_postArray", + "GH_postArray", + Config.FormicaeTab, Config.Tabs.API) + { + } + + protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) + { + pManager.AddTextParameter("HeightArray", "HeightArr", "HeightArr", GH_ParamAccess.item); + pManager.AddTextParameter("Wind Parameters", "WindPar", "WindPar", GH_ParamAccess.item); + pManager.AddTextParameter("WindcomfortClass", "WClass", "WClass", GH_ParamAccess.item); + + } + + protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) + { + + pManager.AddTextParameter("PostArray", "PostArr", "PostArr", GH_ParamAccess.item); + } + + + protected override void SolveInstance(IGH_DataAccess DA) + { + + string heightArrayJson = string.Empty; + string windParamsJson = string.Empty; + string windClass = "lawson_2001"; + if (!DA.GetData(0, ref heightArrayJson)) return; + if (!DA.GetData(1, ref windParamsJson)) return; + if (!DA.GetData(2, ref windClass)) return; + + + + var windParams = JsonConvert.DeserializeObject>(windParamsJson); + object roughness = windParams.TryGetValue("roughness", out roughness) ? roughness : 0; + windParams.Remove("roughness"); + var heightMaps = JsonConvert.DeserializeObject>(heightArrayJson); + + var body = new Dictionary + { + {"heightMaps", heightMaps}, + {"windRose", windParams}, + {"type", "comfort"}, + {"roughness", roughness}, + {"comfortScale", windClass} + }; + string bodyJson = JsonConvert.SerializeObject(body); + DA.SetData(0, bodyJson); + } + + } +} \ No newline at end of file diff --git a/Components/GH_terrainArrays.cs b/Components/GH_terrainArrays.cs new file mode 100644 index 0000000..d446450 --- /dev/null +++ b/Components/GH_terrainArrays.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Grasshopper.Kernel; + +using Grasshopper.Kernel.Types; +using Newtonsoft.Json; +using static Formicae.Helpers.RayTracing; +using static Formicae.Helpers.MeshHelper; + +using System.Drawing; +using System.IO.Compression; +using System.IO; +using System.Text; +namespace Formicae.Components +{ + public class GH_terrainArrays : GH_Component + { + public override Guid ComponentGuid => new Guid("792CBE8E-4903-4F5F-A408-8087DC7FA6CB"); + + protected override Bitmap Icon => null; + + public IGH_GeometricGoo terrain; + + public GH_terrainArrays() + : base("GH_terrainArrays", "FG_TA", + "GH_terrainArrays", + Config.FormicaeTab, Config.Tabs.Geometry) + { + } + + protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) + { + pManager.AddGeometryParameter("Terrain", "T", "", GH_ParamAccess.item); + pManager.AddGeometryParameter("Terrain + Building", "T+B", "", GH_ParamAccess.item); + } + + protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) + { + pManager.AddTextParameter("Height Dictionary", "HeightDict", "HeightDict", GH_ParamAccess.item); + pManager.AddMeshParameter("Analysis Mesh", "AnalysisMesh", "AnalysisMesh", GH_ParamAccess.item); + } + + + protected override void SolveInstance(IGH_DataAccess DA) + { + Rhino.Geometry.Mesh terrainAndBuildings = new Rhino.Geometry.Mesh(); + DA.GetData(0, ref terrain); + DA.GetData(1, ref terrainAndBuildings); + + var terrainToMesh = Remesh(terrain); + var terrainAndBuildingsToMesh = terrainAndBuildings; + + var rectTerrain = GetBase(terrainToMesh); + + var gridPoints = GetPoints(rectTerrain); + var analysisPoints = GetPointsAnalysis(rectTerrain); + + var rayTerrain = HitPointsHeight(gridPoints, terrainToMesh); + Rhino.Geometry.Mesh ProbMesh = CreateMeshFromGridPoints(HitPoints(analysisPoints, terrainToMesh),201,201); + + var rayTerrainAndBuilding = HitPointsHeight(gridPoints, terrainAndBuildingsToMesh); + + double apiMin = rayTerrainAndBuilding.Min(); + double apiMax = rayTerrain.Max(); + + int[] apiBuildingParallel = new int[rayTerrainAndBuilding.Length]; + int[] apiTerrainParallel = new int[rayTerrain.Length]; + + + if (apiMax != apiMin) + { + for (int index = 0; index < rayTerrainAndBuilding.Length; index++) + { + var value = rayTerrainAndBuilding[index]; + var normalizedValue = (value - apiMin) / (apiMax - apiMin) * 255; + apiBuildingParallel[index] = (int)Math.Round(normalizedValue); + } + + for (int index = 0; index < rayTerrain.Length; index++) + { + var value = rayTerrain[index]; + var normalizedValue = (value - apiMin) / (apiMax - apiMin) * 255; + apiTerrainParallel[index] = (int)Math.Round(normalizedValue); + } + } + + List apiBuilding = new List(apiBuildingParallel); + List apiTerrain = new List(apiTerrainParallel); + + var heightMaps = new Dictionary + { + {"terrainHeightArray", apiTerrain}, + {"minHeight", apiMin}, + {"maxHeight", apiMax}, + {"buildingAndTerrainHeightArray", apiBuilding} + }; + + string jsonString = JsonConvert.SerializeObject(heightMaps,Formatting.None); + + DA.SetData(0, jsonString); + DA.SetData(1, ProbMesh); + + + } + + public static byte[] CompressString(string str) + { + byte[] uncompressedBytes = Encoding.UTF8.GetBytes(str); + + using (var memoryStream = new MemoryStream()) + { + using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress)) + { + gzipStream.Write(uncompressedBytes, 0, uncompressedBytes.Length); + } + + return memoryStream.ToArray(); + } + } + + public static string ToBase64String(byte[] bytes) + { + return Convert.ToBase64String(bytes); + } + + } +} \ No newline at end of file diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..40079c2 --- /dev/null +++ b/Config.cs @@ -0,0 +1,26 @@ +namespace Formicae +{ + static class Config + { + public enum FormicaeSubTab + { + Geometry, + API, + Show, + } + + //Name for the GH tab + public static string FormicaeTab { get => " Formicae"; } + public static string Suffix { get => " Formicae"; } + + public static class Tabs + { + public static string Geometry { get => $"{(FormicaeSubTab)0}"; } + public static string API { get => $"{(FormicaeSubTab)1}"; } + public static string Show { get => $"{(FormicaeSubTab)2}"; } + + + + } + } +} diff --git a/Dependencies/DHARTAPI.dll b/Dependencies/DHARTAPI.dll new file mode 100644 index 0000000..9dfcf75 Binary files /dev/null and b/Dependencies/DHARTAPI.dll differ diff --git a/Dependencies/DHARTAPICSharp.dll b/Dependencies/DHARTAPICSharp.dll new file mode 100644 index 0000000..0231dc1 Binary files /dev/null and b/Dependencies/DHARTAPICSharp.dll differ diff --git a/Dependencies/embree3.dll b/Dependencies/embree3.dll new file mode 100644 index 0000000..3d34380 Binary files /dev/null and b/Dependencies/embree3.dll differ diff --git a/Dependencies/tbb.dll b/Dependencies/tbb.dll new file mode 100644 index 0000000..e4aae8e Binary files /dev/null and b/Dependencies/tbb.dll differ diff --git a/Formicae.csproj b/Formicae.csproj index 403356f..0c8f937 100644 --- a/Formicae.csproj +++ b/Formicae.csproj @@ -13,5 +13,11 @@ + + + + Assemblies\DHARTAPICSharp.dll + + \ No newline at end of file diff --git a/Formicae.gha b/Formicae.gha deleted file mode 100644 index 71b314f..0000000 Binary files a/Formicae.gha and /dev/null differ diff --git a/FormicaeComponent.cs b/FormicaeComponent.cs deleted file mode 100644 index 27ec889..0000000 --- a/FormicaeComponent.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Grasshopper; -using Grasshopper.Kernel; -using Rhino.Geometry; -using System; -using System.Collections.Generic; - -namespace Formicae -{ - public class FormicaeComponent : GH_Component - { - /// - /// Each implementation of GH_Component must provide a public - /// constructor without any arguments. - /// Category represents the Tab in which the component will appear, - /// Subcategory the panel. If you use non-existing tab or panel names, - /// new tabs/panels will automatically be created. - /// - public FormicaeComponent() - : base("FormicaeComponent", "Nickname", - "Description", - "Category", "Subcategory") - { - } - - /// - /// Registers all the input parameters for this component. - /// - protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) - { - } - - /// - /// Registers all the output parameters for this component. - /// - protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) - { - } - - /// - /// This is the method that actually does the work. - /// - /// The DA object can be used to retrieve data from input parameters and - /// to store data in output parameters. - protected override void SolveInstance(IGH_DataAccess DA) - { - } - - /// - /// Provides an Icon for every component that will be visible in the User Interface. - /// Icons need to be 24x24 pixels. - /// You can add image files to your project resources and access them like this: - /// return Resources.IconForThisComponent; - /// - protected override System.Drawing.Bitmap Icon => null; - - /// - /// Each component must have a unique Guid to identify it. - /// It is vital this Guid doesn't change otherwise old ghx files - /// that use the old ID will partially fail during loading. - /// - public override Guid ComponentGuid => new Guid("fff4de67-6264-4ddd-af2c-e75df0fe636f"); - } -} \ No newline at end of file diff --git a/Helpers/API/GH_Component_HTTPAsync.cs b/Helpers/API/GH_Component_HTTPAsync.cs new file mode 100644 index 0000000..24beb0b --- /dev/null +++ b/Helpers/API/GH_Component_HTTPAsync.cs @@ -0,0 +1,143 @@ +using Formicae.Templates; +using Grasshopper.Kernel; +using Rhino; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +namespace Formicae.Helpers.API +{ + public abstract class GH_Component_HTTPAsync : GH_Component + { + protected string _response = ""; + protected bool _shouldExpire = false; + protected RequestState _currentState = RequestState.Off; + + public GH_Component_HTTPAsync(string name, string nickname, string description, string category, string subcategory) + : base(name, nickname, description, category, subcategory) + { + } + + protected override void ExpireDownStreamObjects() + { + if (_shouldExpire) + { + base.ExpireDownStreamObjects(); + } + } + + protected void POSTAsync( + string url, + string body, + string contentType, + string authorization, + int timeout) + { + Task.Run(() => + { + try + { + // Compose the request + byte[] data = Encoding.ASCII.GetBytes(body); + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "POST"; + request.ContentType = contentType; + request.ContentLength = data.Length; + request.Timeout = timeout; + + // Handle authorization + if (authorization != null && authorization.Length > 0) + { + ServicePointManager.Expect100Continue = true; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; //the auth type + + request.PreAuthenticate = true; + request.Headers.Add("Authorization", authorization); + } + else + { + request.Credentials = CredentialCache.DefaultCredentials; + } + + using (var stream = request.GetRequestStream()) + { + stream.Write(data, 0, data.Length); + } + var res = request.GetResponse(); + _response = new StreamReader(res.GetResponseStream()).ReadToEnd(); + + _currentState = RequestState.Done; + + _shouldExpire = true; + RhinoApp.InvokeOnUiThread((Action)delegate { ExpireSolution(true); }); + } + catch (Exception ex) + { + _response = ex.Message; + + _currentState = RequestState.Error; + + _shouldExpire = true; + RhinoApp.InvokeOnUiThread((Action)delegate { ExpireSolution(true); }); + + return; + } + }); + } + + + protected void GETAsync( + string url, + string authorization, + int timeout) + { + Task.Run(() => + { + try + { + // Compose the request + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "GET"; + request.Timeout = timeout; + + // Handle authorization + if (authorization != null && authorization.Length > 0) + { + ServicePointManager.Expect100Continue = true; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; //the auth type + + request.PreAuthenticate = true; + request.Headers.Add("Authorization", authorization); + } + else + { + request.Credentials = CredentialCache.DefaultCredentials; + } + + var res = request.GetResponse(); + _response = new StreamReader(res.GetResponseStream()).ReadToEnd(); + + _currentState = RequestState.Done; + + _shouldExpire = true; + RhinoApp.InvokeOnUiThread((Action)delegate { ExpireSolution(true); }); + } + catch (Exception ex) + { + _response = ex.Message; + + _currentState = RequestState.Error; + + _shouldExpire = true; + RhinoApp.InvokeOnUiThread((Action)delegate { ExpireSolution(true); }); + + return; + } + }); + } + } +} \ No newline at end of file diff --git a/Helpers/API/GH_Component_HTTPSync.cs b/Helpers/API/GH_Component_HTTPSync.cs new file mode 100644 index 0000000..49533fc --- /dev/null +++ b/Helpers/API/GH_Component_HTTPSync.cs @@ -0,0 +1,105 @@ +using Formicae.Templates; +using Grasshopper.Kernel; +using Rhino; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +namespace Formicae.Helpers.API +{ + public abstract class GH_Component_HTTPSync : GH_Component + { + public GH_Component_HTTPSync(string name, string nickname, string description, string category, string subcategory) + : base(name, nickname, description, category, subcategory) + { + } + + protected string POST( + string url, + string body, + string contentType, + string authorization, + int timeout) + { + try + { + // Compose the request + byte[] data = Encoding.ASCII.GetBytes(body); + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "POST"; + request.ContentType = contentType; + request.ContentLength = data.Length; + request.Timeout = timeout; + + // Handle authorization + if (authorization != null && authorization.Length > 0) + { + System.Net.ServicePointManager.Expect100Continue = true; + System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //the auth type + + request.PreAuthenticate = true; + request.Headers.Add("Authorization", authorization); + } + else + { + request.Credentials = CredentialCache.DefaultCredentials; + } + + using (var stream = request.GetRequestStream()) + { + stream.Write(data, 0, data.Length); + } + var res = request.GetResponse(); + var response = new StreamReader(res.GetResponseStream()).ReadToEnd(); + return response; + } + catch (Exception ex) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Something went wrong: " + ex.Message); + return ""; + } + } + + protected string GET( + string url, + string authorization, + int timeout) + { + try + { + // Compose the request + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "GET"; + request.Timeout = timeout; + + // Handle authorization + if (authorization != null && authorization.Length > 0) + { + System.Net.ServicePointManager.Expect100Continue = true; + System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; //the auth type + + request.PreAuthenticate = true; + request.Headers.Add("Authorization", authorization); + } + else + { + request.Credentials = CredentialCache.DefaultCredentials; + } + + var res = request.GetResponse(); + var response = new StreamReader(res.GetResponseStream()).ReadToEnd(); + + return response; + } + catch (Exception ex) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Something went wrong: " + ex.Message); + return ""; + } + } + } +} \ No newline at end of file diff --git a/api/OAuthHandler.cs b/Helpers/API/OAuthHandler.cs similarity index 98% rename from api/OAuthHandler.cs rename to Helpers/API/OAuthHandler.cs index acc2f8f..e7891e2 100644 --- a/api/OAuthHandler.cs +++ b/Helpers/API/OAuthHandler.cs @@ -12,7 +12,7 @@ using System.Net.Http; using System.Threading; -namespace Formicae.api +namespace Formicae.Helpers.API { @@ -100,7 +100,7 @@ public static async Task GetAccessToken() // You had commented out the state encryption check, ensuring it's intentional. // var incoming = context.Request.QueryString.Get("state"); - var buffer = System.Text.Encoding.UTF8.GetBytes("success!"); + var buffer = Encoding.UTF8.GetBytes("success!"); response.ContentLength64 = buffer.Length; response.OutputStream.WriteAsync(buffer, 0, buffer.Length).ContinueWith((task) => { diff --git a/Helpers/API/RequestStateEnum.cs b/Helpers/API/RequestStateEnum.cs new file mode 100644 index 0000000..5923ad9 --- /dev/null +++ b/Helpers/API/RequestStateEnum.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Formicae.Templates +{ + public enum RequestState + { + Off, + Idle, + Requesting, + Done, + Error + }; +} \ No newline at end of file diff --git a/Helpers/MeshHelper.cs b/Helpers/MeshHelper.cs index e15d422..b0a774e 100644 --- a/Helpers/MeshHelper.cs +++ b/Helpers/MeshHelper.cs @@ -4,7 +4,8 @@ using System.Text; using System.Threading.Tasks; using Rhino.Geometry; -using Grasshopper; +using Rhino.DocObjects; + using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using GH_IO.Serialization; @@ -13,186 +14,139 @@ using Rhino.Geometry.Intersect; using System.Drawing.Printing; using System.Security.Policy; +using System.Collections.Concurrent; namespace Formicae.Helpers { - public static class MeshHelper + public class MeshHelper { - /// - /// Creates a single face with squared offset (read vertically) - /// - /// Bot left - /// - /// - public static Mesh GetSingleMeshForResult(Plane plane) + public static Rhino.Geometry.Mesh Remesh(IGH_GeometricGoo goo) { - // 1 meter - double offset = 1; - Mesh m = new Mesh(); - m.Vertices.Add(plane.Origin); - m.Vertices.Add(plane.Origin + plane.YAxis * offset); - m.Vertices.Add(plane.Origin + plane.YAxis * offset + plane.XAxis * offset); - m.Vertices.Add(plane.Origin + plane.XAxis * offset); - m.Faces.AddFace(0, 1, 2, 3); - return m; - } + Guid id = goo.ReferenceID; + var rhinoObj = new RhinoObject[] { RhinoDoc.ActiveDoc.Objects.Find(id) }; + if (rhinoObj == null) return null; - /// - /// Create a mesh grid (Read vertically) - /// - /// Result Plane - /// 200 X 200 300 X 300 Grid etc.. - public static Mesh GetGridMeshForResult(Plane originPlane, double gridTotalDistance , double gridresolution) - { - Mesh resultGrid = new Mesh(); - for (int i = 0; i < gridTotalDistance; i++) - { - //Create plane in x direction - Plane offsetedPlane = originPlane; - offsetedPlane.Translate(originPlane.XAxis * i); - Mesh OffsetMeshinX = GetSingleMeshForResult(offsetedPlane); + ObjRef[] getMesh = Rhino.DocObjects.RhinoObject.GetRenderMeshesWithUpdatedTCs(rhinoObj, false, false, false, false); //hidden objects won't be ignored + if (getMesh.Length == 0) return null; - for (int j = 0; j < gridTotalDistance; j++) - { - //Translate in y direction - Mesh tempMesh = OffsetMeshinX.DuplicateMesh(); - tempMesh.Translate(originPlane.YAxis * j); - resultGrid.Append(tempMesh); - } - } - return resultGrid; + return getMesh[0].Mesh(); } - /// - /// Create a mesh grid (Read vertically) - /// - /// Top left corner - /// - public static Mesh GetPlaneForMeshSimulation(Plane plane) - { - double offset = 1.5; - Mesh m = new Mesh(); - m.Vertices.Add(plane.Origin); - m.Vertices.Add(plane.Origin - plane.YAxis * offset); - m.Vertices.Add(plane.Origin - (plane.YAxis * offset) + (plane.XAxis * offset)); - m.Vertices.Add(plane.Origin + plane.XAxis * offset); - m.Faces.AddFace(0, 1, 2, 3); - return m; + public static Rectangle3d GetBase(Rhino.Geometry.Mesh mesh) + { + BoundingBox box = mesh.GetBoundingBox(false); + + double zOffset = 100; + Point3d center = new Point3d((box.Min.X + box.Max.X) / 2, (box.Min.Y + box.Max.Y) / 2, box.Max.Z + zOffset); + double length = 500; + double width = 500; + Point3d rectStart = new Point3d(center.X - length / 2, center.Y - width / 2, center.Z); + Point3d rectEnd = new Point3d(center.X + length / 2, center.Y + width / 2, center.Z); + Rectangle3d rect = new Rectangle3d(new Plane(center, Vector3d.ZAxis), rectStart, rectEnd); + + return rect; } - [Obsolete] - public static Mesh GetGridMeshForSimulation(Plane OriginPlane, double GridtTotalDistance) + public static Point3d[] GetPoints(Rectangle3d rect) { - //Too slow - Mesh resultGrid = new Mesh(); - - for (int i = 0; i < GridtTotalDistance; i++) + int divisions = (int)Math.Sqrt(250000) - 1; + double width = rect.Width; + double height = rect.Height; + double spacingX = width / divisions; + double spacingY = height / divisions; + + int arrayLength = (divisions + 1) * (divisions + 1); + Point3d[] points = new Point3d[arrayLength]; + for (int i = 0; i <= divisions; i++) { - //Create plane in Y direction - Plane offsetedPlane = OriginPlane; - offsetedPlane.Translate(OriginPlane.XAxis * i); - Mesh OffsetMeshinY = GetPlaneForMeshSimulation(offsetedPlane); - - for (int j = 0; j < GridtTotalDistance; j++) + for (int j = 0; j <= divisions; j++) { - //Translate in X direction - Mesh tempMesh = OffsetMeshinY.DuplicateMesh(); - tempMesh.Translate(OriginPlane.XAxis * j); - resultGrid.Append(tempMesh); + + double x = rect.Corner(0).X + (j * spacingX); + double y = rect.Corner(0).Y + (i * spacingY); + Point3d pt = new Point3d(x, y, rect.Corner(0).Z); + int index = (i * (divisions + 1)) + j; + points[index] = pt; } } - return resultGrid; + + return points; } - /// - /// - /// - /// - /// - /// - /// - public static List GetGridPointsForSimulation(Plane OriginPlane, double GridtTotalDistance , double gridResolution) - { - var pts = new List(); - for (int i = 0; i < GridtTotalDistance; i++) + public static Point3d[] GetPointsAnalysis(Rectangle3d rect) + { + + Point3d center = new Point3d( + (rect.Corner(0).X + rect.Corner(2).X) / 2, + (rect.Corner(0).Y + rect.Corner(2).Y) / 2, + rect.Corner(0).Z); + + double desiredLength = 200; + double desiredWidth = 200; + + Point3d newRectStart = new Point3d(center.X - desiredLength / 2, center.Y - desiredWidth / 2, center.Z); + Point3d newRectEnd = new Point3d(center.X + desiredLength / 2, center.Y + desiredWidth / 2, center.Z); + Rectangle3d newRect = new Rectangle3d(new Plane(center, Vector3d.ZAxis), newRectStart, newRectEnd); + int divisions = (int)Math.Sqrt(40000); + double width = newRect.Width; + double height = newRect.Height; + double spacingX = width / divisions; + double spacingY = height / divisions; + + Point3d[] points = new Point3d[(divisions + 1) * (divisions + 1)]; // Adjust for one extra in each dimension + + for (int i = 0; i <= divisions; i++) { - - //Create plane in Y direction - Plane offsetedPlane = OriginPlane; - offsetedPlane.Translate(OriginPlane.YAxis * -i * gridResolution); - Point3d pointToOffset = offsetedPlane.Origin - OriginPlane.YAxis * gridResolution / 2; - //Create plane in Y direction - //Point3d pointToOffset = OriginPlane.Origin - (OriginPlane.YAxis) * gridResolution / 2*i; - - for (int j = 0; j < GridtTotalDistance; j++) + for (int j = 0; j <= divisions; j++) { - //Translate in X direction - Point3d tempPt = new Point3d(pointToOffset) + (OriginPlane.XAxis) * gridResolution / 2; // move the point to the right - tempPt = tempPt + OriginPlane.XAxis * gridResolution * j; // move the point with the array - //Point3d tempPt = new Point3d(pointToOffset) + OriginPlane.XAxis * gridResolution * j ; - pts.Add(tempPt); + double x = newRect.Corner(0).X + (j * spacingX); + double y = newRect.Corner(0).Y + (i * spacingY); + points[i * (divisions + 1) + j] = new Point3d(x, y, newRect.Corner(0).Z); // Assuming flat Z } } - return pts; + return points; } - /// - /// - /// - /// - /// - /// - /// - public static Mesh GetResultMeshRowMajor(Plane OriginPlane, double GridFaceCount, double gridResolution) + + + + public static Mesh CreateMeshFromGridPoints(Point3d[] points, int gridWidth, int gridHeight) { + if (points == null || points.Length == 0) + throw new ArgumentException("Points array is null or empty", nameof(points)); + if (points.Length != gridWidth * gridHeight) + throw new ArgumentException("Points array size does not match grid dimensions", nameof(points)); + Mesh mesh = new Mesh(); - for (int i = 0; i < GridFaceCount; i++) + foreach (Point3d point in points) { + mesh.Vertices.Add(point); + } - //Create plane in Y direction - Plane offsetedPlane = OriginPlane; - offsetedPlane.Translate(OriginPlane.YAxis * -i * gridResolution); - Mesh OffsetMeshinY = GetPlaneForMeshSimulation(offsetedPlane); - - - for (int j = 0; j < GridFaceCount; j++) + // Create faces + for (int y = 0; y < gridHeight - 1; y++) + { + for (int x = 0; x < gridWidth - 1; x++) { - //Translate in X direction - Mesh tempMesh = OffsetMeshinY.DuplicateMesh(); - tempMesh.Translate(OriginPlane.XAxis * j * gridResolution); - mesh.Append(tempMesh); + int lowerLeft = y * gridWidth + x; + int lowerRight = y * gridWidth + x + 1; + int upperLeft = (y + 1) * gridWidth + x; + int upperRight = (y + 1) * gridWidth + x + 1; + + mesh.Faces.AddFace(lowerLeft, lowerRight, upperRight, upperLeft); } } + mesh.Normals.ComputeNormals(); + mesh.Compact(); + return mesh; } - public static List ProjectPointsDownardOnMesh(IEnumerable pts, Mesh mesh) - { - Mesh[] meshArray = new Mesh[1]; - meshArray[0] = mesh; - var projectedPts = Intersection.ProjectPointsToMeshes(meshArray, pts, Vector3d.ZAxis * -1, RhinoDoc.ActiveDoc.ModelAbsoluteTolerance).ToList(); - return projectedPts; - } - /// - /// Drapes a mesh onto anthor assuming its higher - /// - /// - /// - /// - public static Mesh DrapeMesh(Mesh MeshToDrape, Mesh TargetMesh) - { - var pointsToProject = MeshToDrape.Vertices.ToPoint3dArray(); - var projectdPts = ProjectPointsDownardOnMesh(pointsToProject, TargetMesh); - Mesh drappedMesh = new Mesh(); - drappedMesh.Vertices.AddVertices(projectdPts); - drappedMesh.Faces.AddFaces(MeshToDrape.Faces); - return drappedMesh; - } } } diff --git a/Helpers/RayTracing.cs b/Helpers/RayTracing.cs new file mode 100644 index 0000000..7bf748b --- /dev/null +++ b/Helpers/RayTracing.cs @@ -0,0 +1,75 @@ + +using Rhino.Geometry; +using DHARTAPI.Geometry; +using DHARTAPI.RayTracing; +using System.Diagnostics; +using System.Threading.Tasks; + + +namespace Formicae.Helpers +{ + public class RayTracing + { + public static Point3d[] HitPoints(Point3d[] points, Rhino.Geometry.Mesh contextMesh) + { + Point3d[] points_ = new Point3d[points.Length]; + MeshInfo _contextMesh = new MeshInfo(contextMesh.Faces.ToIntArray(true), contextMesh.Vertices.ToFloatArray()); + EmbreeBVH bvh = new EmbreeBVH(_contextMesh); + + var analysisPoints = new DHARTAPI.Vector3D[points.Length]; + for (int i = 0; i < points.Length; i++) + analysisPoints[i] = new DHARTAPI.Vector3D((float)points[i].X, (float)points[i].Y, (float)points[i].Z); + + + var direction_vector = new DHARTAPI.Vector3D(0, 0, -1); + + + DHARTAPI.Vector3D[] hitPoints = new DHARTAPI.Vector3D[points.Length]; + + Parallel.For(0, points.Length, i => + { + hitPoints[i] = EmbreeRaytracer.IntersectForPoint(bvh, analysisPoints[i], direction_vector); + points_[i] = new Point3d(hitPoints[i].x, hitPoints[i].y, hitPoints[i].z); ; + }); + + return points_; + } + + + public static double[] HitPointsHeight(Point3d[] points, Rhino.Geometry.Mesh contextMesh) + { + Point3d[] points_ = new Point3d[points.Length]; + double[] height_ = new double[points.Length]; + + MeshInfo _contextMesh = new MeshInfo(contextMesh.Faces.ToIntArray(true), contextMesh.Vertices.ToFloatArray()); + EmbreeBVH bvh = new EmbreeBVH(_contextMesh); + + + var analysisPoints = new DHARTAPI.Vector3D[points.Length]; + for (int i = 0; i < points.Length; i++) + analysisPoints[i] = new DHARTAPI.Vector3D((float)points[i].X, (float)points[i].Y, (float)points[i].Z); + + + var direction_vector = new DHARTAPI.Vector3D(0, 0, -1); + DHARTAPI.Vector3D[] hitPoints = new DHARTAPI.Vector3D[points.Length]; + Parallel.For(0, points.Length, i => + { + + hitPoints[i] = EmbreeRaytracer.IntersectForPoint(bvh, analysisPoints[i], direction_vector); + points_[i] = new Point3d(hitPoints[i].x, hitPoints[i].y, hitPoints[i].z); + height_[i] = hitPoints[i].z; + }); + + return height_; + } + + + public static void LogTime(ref Stopwatch sw, string text) + { + sw.Stop(); + Rhino.RhinoApp.WriteLine($"{text}: {sw.ElapsedMilliseconds} ms"); + sw.Restart(); + } + + } +} diff --git a/Supporting Grasshopper Scripts/forma-api.gh b/Supporting Grasshopper Scripts/forma-api.gh index 6e82870..4f1aee3 100644 Binary files a/Supporting Grasshopper Scripts/forma-api.gh and b/Supporting Grasshopper Scripts/forma-api.gh differ diff --git a/Supporting Grasshopper Scripts/rhino/sample.3dm b/Supporting Grasshopper Scripts/rhino/sample.3dm index 2bd61c5..641bb20 100644 Binary files a/Supporting Grasshopper Scripts/rhino/sample.3dm and b/Supporting Grasshopper Scripts/rhino/sample.3dm differ diff --git a/Supporting Grasshopper Scripts/rhino/sample.3dm.rhl b/Supporting Grasshopper Scripts/rhino/sample.3dm.rhl deleted file mode 100644 index 834a06e..0000000 --- a/Supporting Grasshopper Scripts/rhino/sample.3dm.rhl +++ /dev/null @@ -1,3 +0,0 @@ -mm1039 -MM-C0D1E-028 -Wednesday, February 14, 2024 \ No newline at end of file diff --git a/Supporting Grasshopper Scripts/input.json b/Supporting Grasshopper Scripts/sample/input.json similarity index 100% rename from Supporting Grasshopper Scripts/input.json rename to Supporting Grasshopper Scripts/sample/input.json diff --git a/api/sample/input_without_grids - simplified.json b/Supporting Grasshopper Scripts/sample/input_without_grids - simplified.json similarity index 100% rename from api/sample/input_without_grids - simplified.json rename to Supporting Grasshopper Scripts/sample/input_without_grids - simplified.json diff --git a/Types/Buildings.cs b/Types/Buildings.cs deleted file mode 100644 index c829921..0000000 --- a/Types/Buildings.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Grasshopper.Kernel; -using Rhino.Geometry; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Formicae.Types -{ - public class Buildings - { - public Brep buildingBreps; - - public List buildings; - - public Buildings() { } - - public Mesh previewMesh => GetBuildingsPreviewMesh(); - - public Buildings(Brep brep) - { - buildingBreps = brep; - } - - public Buildings(Listbreps) - { - Brep brep = new Brep(); - //foreach(var b in breps) - //{ - // brep.Append(b); - //} - //buildingBreps = brep; - - this.buildings = breps; - } - - public Mesh GetBuildingsPreviewMesh() - { - //Mesh mesh = new Mesh(); - //Mesh[] meshes = Mesh.CreateFromBrep(this.buildingBreps, MeshingParameters.FastRenderMesh); - //foreach (var m in meshes) - //{ - // mesh.Append(m); - //} - //return mesh; - - Mesh mesh = new Mesh(); - foreach ( var bldg in buildings ) - { - mesh.Append(Mesh.CreateFromBrep(bldg, MeshingParameters.FastRenderMesh)); - } - - return mesh; - } - - - } -} diff --git a/Types/HeightMap.cs b/Types/HeightMap.cs deleted file mode 100644 index e476bd2..0000000 --- a/Types/HeightMap.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Grasshopper.Kernel; -using Rhino.Geometry; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Rhino.Geometry.Intersect; -using Formicae.Helpers; -using System.Diagnostics; - -namespace Formicae.Types -{ - public class HeightMap - { - public WindSimulationModel Model { get; set; } - - public HeightMap() { } - - public HeightMap(WindSimulationModel model) - { - this.Model = model; - } - - public List HeightMapWithoutBuildings() - { - List heights = new List(); - List projectedPts = MeshHelper.ProjectPointsDownardOnMesh(Model.SimulationBox.LiftedPts, Model.GetModelMeshWithoutBuildings()); - foreach (Point3d p in projectedPts) - { - heights.Add(p.Z); - } - return heights; - } - - public List HeightMapWithBuildings() - { - List heights = new List(); - List projectedPts = MeshHelper.ProjectPointsDownardOnMesh(Model.SimulationBox.LiftedPts, Model.GetModelMeshWithBuildings()); - foreach (Point3d p in projectedPts) - { - heights.Add(p.Z); - } - return heights; - } - - public static List MapToDomain(List values, double domainMin, double domainMax) - { - List mappedValues = new List(); - double range = domainMax - domainMin; - - Stopwatch stopwatch = new Stopwatch(); - stopwatch.Start(); - foreach (var value in values) - { - - double mappedValue = ((value - values.Min()) / (values.Max() - values.Min())) * range + domainMin; - mappedValues.Add(mappedValue); - } - - stopwatch.Stop(); - var profileSpan = stopwatch.Elapsed; - Rhino.RhinoApp.WriteLine(profileSpan.ToString()); - - return mappedValues; - } - } -} diff --git a/Types/SimulationBox.cs b/Types/SimulationBox.cs deleted file mode 100644 index 22045bb..0000000 --- a/Types/SimulationBox.cs +++ /dev/null @@ -1,399 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Rhino.Geometry; -using Grasshopper; -using Grasshopper.Kernel; -using Grasshopper.Kernel.Types; -using GH_IO.Serialization; -using Rhino; -using System.Runtime.InteropServices.WindowsRuntime; -using Formicae.Helpers; - - - - -namespace Formicae.Types -{ - /// - /// A box that is used to orient and simulate the geometry - /// - public class SimulationBox : IGH_Goo,IGH_GeometricGoo,IGH_PreviewData - { - - #region Properties - public BoundingBox BoundingBox { get; set; } - public Brep BoundingBoxBrep { get; set; } - - - public bool IsValid => this.IsABox(); - - public string IsValidWhyNot => throw new NotImplementedException(); - - public string TypeName => "SimulationBox"; - - public string TypeDescription => "A bounding box used to extract the simulation grid for wind analysis from Forma."; - - public BoundingBox Boundingbox => throw new NotImplementedException(); - - public Guid ReferenceID { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - - public bool IsReferencedGeometry => this.BoundingBoxBrep != null; - - public bool IsGeometryLoaded => this.BoundingBoxBrep != null; - - public BoundingBox ClippingBox => BoundingBoxBrep?.GetBoundingBox(false) ?? BoundingBox.Unset; - - public double ResultMeshFaceCount = 200; // 300 in meters - - public double SimulationGridFaceCount = 500; // 750 in meters - - public double SimulationGridResolution = 1.5; - - public double BoxHeight => GetBoxHeight(); - - public double SimulationGridDistance = 750; - - public double ResultGridDistance = 300; - - /// - /// Points that can be used to calculate height always heigher than the Simulation Box Brep - /// - public List LiftedPts => GetSimulationPointsUp(); - - /// - /// Result mesh that is heigher than the Simulation Box, Can be used to drape - /// - public Mesh LiftedResultMesh => GetResultMeshUp(); - - - #endregion - - #region constructors - - public SimulationBox() - { - - } - - /// - /// Create a simulation bounding box based on BB. - /// - /// - public SimulationBox(BoundingBox box) - { - this.BoundingBox = box; - this.BoundingBoxBrep = box.ToBrep(); - - } - - /// - /// Createa a simulation bounding box based on a brep - /// - /// - public SimulationBox (Brep box ) - { - this.BoundingBoxBrep = box; - } - - #endregion - - #region IGH_Goo - - public IGH_Goo Duplicate() - { - throw new NotImplementedException(); - } - - public IGH_GooProxy EmitProxy() - { - throw new NotImplementedException(); - } - - public bool CastFrom(object source) - { - throw new NotImplementedException(); - } - - public bool CastTo(out T target) - { - throw new NotImplementedException(); - } - - public object ScriptVariable() - { - throw new NotImplementedException(); - } - - public bool Write(GH_IWriter writer) - { - throw new NotImplementedException(); - } - - public bool Read(GH_IReader reader) - { - throw new NotImplementedException(); - - } - - #endregion - - #region IGH_GeometricGoo - - public IGH_GeometricGoo DuplicateGeometry() - { - return this; - } - - public BoundingBox GetBoundingBox(Transform xform) - { - throw new NotImplementedException(); - } - - public IGH_GeometricGoo Transform(Transform xform) - { - throw new NotImplementedException(); - } - - public IGH_GeometricGoo Morph(SpaceMorph xmorph) - { - throw new NotImplementedException(); - } - - public bool LoadGeometry() - { - throw new NotImplementedException(); - } - - public bool LoadGeometry(RhinoDoc doc) - { - throw new NotImplementedException(); - } - - public void ClearCaches() - { - throw new NotImplementedException(); - } - - - #endregion - - #region IGH_PreviewData - - public void DrawViewportWires(GH_PreviewWireArgs args) - { - args.Pipeline.DrawDottedPolyline(GetResultMeshOutline(), System.Drawing.Color.Magenta,true); - args.Pipeline.Draw3dText("Interest Area", System.Drawing.Color.Black, this.GetTopCenterPlane(), 3, "Arial"); - - } - - public void DrawViewportMeshes(GH_PreviewMeshArgs args) - { - // throw new NotImplementedException(); - args.Pipeline.DrawDottedPolyline(GetResultMeshOutline(), System.Drawing.Color.Magenta, true); - args.Pipeline.Draw3dText("Interest Area", System.Drawing.Color.Black, this.GetTopCenterPlane(), 3, "Arial"); - } - - #endregion - - #region Simulation grid - - /// - /// Checks if the brep is a box based on the number of points - /// - /// True if the brep has only 8 points - public bool IsABox() - { - return this.BoundingBoxBrep.Vertices.Count == 8; - } - - - /// - /// Get an oriented plane at the lowest point of the bounding box - /// - /// - public Plane GetGridPlaneForBotLeftCorner() - { - var Brepvertices = this.BoundingBoxBrep.Vertices; - var BrepPts = Brepvertices.Select(a => a.Location).ToList(); - var LowestX = Brepvertices.Select(a => a.Location).Select(b => b.X).Min(); - var LowestY = Brepvertices.Select(a => a.Location).Select(b => b.Y).Min(); - var LowestZ = Brepvertices.Select(a => a.Location).Select(b => b.Z).Min(); - var MaxX = Brepvertices.Select(a => a.Location).Select(b => b.X).Max(); - var MaxY = Brepvertices.Select(a => a.Location).Select(b => b.Y).Max(); - - Point3d Pa = new Point3d(); - Point3d Pb = new Point3d(); - Point3d Pc = new Point3d(); - - foreach (var pt in BrepPts) - { - if (pt.X == LowestX && pt.Y == LowestY && pt.Z == LowestZ) - { - Pa = pt; - } - if (pt.X == MaxX && pt.Y == LowestY && pt.Z == LowestZ) - { - Pb = pt; - } - if (pt.X == LowestX && pt.Y == MaxY && pt.Z == LowestZ) - { - Pc = pt; - } - } - - Vector3d u = Pb - Pa; - u.Unitize(); - Vector3d v = Pc - Pa; - v.Unitize(); - Point3d origin = Pa; - - Plane plane = new Plane(origin, u, v); - return plane; - - } - - - /// - /// Get the result plane to generate the grid for the result grid - /// - /// - public Plane GetResultPlane() - { - var botleftcorner = GetGridPlaneForBotLeftCorner(); - //double leftoverspace = (this.SimulationGridFaceCount - this.ResultGridDistance) / 2; - botleftcorner.Translate(botleftcorner.XAxis * 225); - botleftcorner.Translate(botleftcorner.YAxis * 525); - return botleftcorner; - } - - /// - /// Gets the simulation Plane to generate the simulaiton grid - /// - /// - public Plane GetSimulationPlane() - { - var botleftcorner = GetGridPlaneForBotLeftCorner(); - botleftcorner.Translate(botleftcorner.YAxis * this.SimulationGridDistance); - return botleftcorner; - } - - ///// - ///// Gets the grid for the result to be colored - ///// - ///// - //public Mesh GetResultMeshGrid () - //{ - // return MeshHelper.GetGridMeshForResult(GetResultPlane(), this.ResultGridDistance,1.5); - //} - - - - /// - /// Gets the grid for the result to be colored - /// - /// - public Mesh GetResultMeshGrid() - { - return MeshHelper.GetResultMeshRowMajor(GetResultPlane(), this.ResultMeshFaceCount, this.SimulationGridResolution); //Same resolution - } - - [Obsolete] - /// - /// TOO SLOW!! Get the grid for the simulation to calcualte height maps - /// - /// - public Mesh GetSimulationMesh() - { - return MeshHelper.GetGridMeshForSimulation(GetSimulationPlane(), this.SimulationGridFaceCount); - } - - - - - public List GetSimulationPoints() - { - return MeshHelper.GetGridPointsForSimulation(GetSimulationPlane(),this.SimulationGridFaceCount, this.SimulationGridResolution); - } - - - - #endregion - - #region Methods - - public override string ToString() - { - return $"A {TypeName} with a simulation grid of size {this.SimulationGridFaceCount} * {this.SimulationGridFaceCount} of resolution {this.SimulationGridResolution} (Distance between points)" + - $"\nAt the center of which an interest area grid (resultGrid) of size {this.ResultMeshFaceCount} * {this.ResultMeshFaceCount} of resolution {this.SimulationGridResolution} "; - } - - /// - /// Gets the center point in the middle of the top Surface - /// - /// - public Point3d GetTopCenterPoint() - { - return this.BoundingBox.GetCorners()[4] + this.BoundingBox.GetCorners()[7] / 2; - } - - /// - /// Gets the result mesh outline for Viz - /// - /// - public Polyline GetResultMeshOutline() - { - var plane = GetGridPlaneForBotLeftCorner(); - plane.Origin = GetTopCenterPoint(); - Rectangle3d rect = new Rectangle3d(plane, this.ResultMeshFaceCount, this.ResultMeshFaceCount); - return rect.ToPolyline(); - } - - /// - /// Gets a plane in the center of the top surface - /// - /// - public Plane GetTopCenterPlane() - { - var plane = GetGridPlaneForBotLeftCorner(); - plane.Origin = GetTopCenterPoint(); - return plane; - } - - public double GetBoxHeight() - { - // return this.BoundingBox.GetCorners()[7].Z - this.BoundingBox.GetCorners()[0].Z; - var Brepvertices = this.BoundingBoxBrep.Vertices; - var LowestZ = Brepvertices.Select(a => a.Location).Select(b => b.Z).Min(); - var MaxZ = Brepvertices.Select(a => a.Location).Select(b => b.Z).Max(); - return MaxZ - LowestZ; - } - - - public List GetSimulationPointsUp() - { - var lowSimPts = GetSimulationPoints(); - List LiftedSimPts = new List(); - foreach (var simPt in lowSimPts) - { - LiftedSimPts.Add(simPt + Vector3d.ZAxis * this.BoxHeight * 1.1); - } - return LiftedSimPts; - } - - /// - /// Put the result mesh heigher than the Simulation Box - /// - /// - public Mesh GetResultMeshUp() - { - Mesh mesh = GetResultMeshGrid(); - mesh.Translate(Vector3d.ZAxis * this.BoxHeight * 1.1); - return mesh; - } - - #endregion - } -} diff --git a/Types/Terrain.cs b/Types/Terrain.cs deleted file mode 100644 index 4407f17..0000000 --- a/Types/Terrain.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Rhino.Geometry; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Formicae.Types -{ - public class Terrain - { - public Mesh terrainMesh; - public Terrain() { } - public Terrain(Mesh mesh) - { - terrainMesh = mesh; - } - - } -} diff --git a/Types/WindSimulationModel.cs b/Types/WindSimulationModel.cs deleted file mode 100644 index a06553b..0000000 --- a/Types/WindSimulationModel.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Formicae.Helpers; -using Rhino.Geometry; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Formicae.Types -{ - public class WindSimulationModel - { - public WindSimulationModel() { } - - public Buildings Buildings { get; set; } - public Terrain Terrain { get; set; } - public SimulationBox SimulationBox { get; set; } - - public Mesh ModelWithBuildings => GetModelMeshWithBuildings(); - public Mesh ModelwithoutBuildings => GetModelMeshWithoutBuildings(); - - public Mesh DrapedResultMesh => GetResultMeshDraped(); - - public WindSimulationModel(Buildings blgs , Terrain terrain, SimulationBox simBox) - { - this.Buildings = blgs; - this.Terrain = terrain; - this.SimulationBox = simBox; - } - - public Mesh GetModelMeshWithBuildings() - { - Mesh mesh = new Mesh(); - mesh.Append(Buildings.previewMesh); - mesh.Append(Terrain.terrainMesh); - return mesh; - } - - public Mesh GetModelMeshWithoutBuildings() - { - Mesh mesh = new Mesh(); - mesh.Append(Terrain.terrainMesh); - return mesh; - } - - public Mesh GetResultMeshDraped() - { - return MeshHelper.DrapeMesh(this.SimulationBox.LiftedResultMesh, this.Terrain.terrainMesh); - } - - - } -}