├── .gitignore ├── Source ├── karambaToSofistik │ ├── Libraries │ │ ├── GH_IO.dll │ │ ├── karamba.gha │ │ ├── Grasshopper.dll │ │ └── RhinoCommon.dll │ ├── Resources │ │ └── icon.png │ ├── karambaToSofistikInfo.cs │ ├── Classes │ │ ├── Beam.cs │ │ ├── Node.cs │ │ ├── Material.cs │ │ ├── Load.cs │ │ ├── Parser.cs │ │ └── CrossSection.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Resource.Designer.cs │ ├── karambaToSofistik.csproj │ ├── Resource.resx │ └── karambaToSofistikComponent.cs └── karambaToSofistik.sln ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | Source/GhToSofistik/bin 2 | Source/GhToSofistik/obj 3 | Bin/ 4 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Libraries/GH_IO.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlbericTrancart/karambaToSofistik/HEAD/Source/karambaToSofistik/Libraries/GH_IO.dll -------------------------------------------------------------------------------- /Source/karambaToSofistik/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlbericTrancart/karambaToSofistik/HEAD/Source/karambaToSofistik/Resources/icon.png -------------------------------------------------------------------------------- /Source/karambaToSofistik/Libraries/karamba.gha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlbericTrancart/karambaToSofistik/HEAD/Source/karambaToSofistik/Libraries/karamba.gha -------------------------------------------------------------------------------- /Source/karambaToSofistik/Libraries/Grasshopper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlbericTrancart/karambaToSofistik/HEAD/Source/karambaToSofistik/Libraries/Grasshopper.dll -------------------------------------------------------------------------------- /Source/karambaToSofistik/Libraries/RhinoCommon.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlbericTrancart/karambaToSofistik/HEAD/Source/karambaToSofistik/Libraries/RhinoCommon.dll -------------------------------------------------------------------------------- /Source/karambaToSofistik/karambaToSofistikInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using Grasshopper.Kernel; 4 | 5 | namespace karambaToSofistik { 6 | // Component info 7 | public class karambaToSofistikInfo : GH_AssemblyInfo { 8 | public override string Name { get { return "karambaToSofistik"; } } 9 | public override Bitmap Icon { get { return Resource.Icon; } } 10 | public override string Description { get { return "Convert a model from Karamba to a .dat file readable by Sofistik"; } } 11 | public override Guid Id { get { return new Guid("c39f7c34-8a3f-4035-8673-c35a21ff4266"); } } 12 | public override string AuthorName { get { return "Albéric Trancart (ENPC)"; } } 13 | public override string AuthorContact { get { return "alberic.trancart@eleves.enpc.fr"; } } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/karambaToSofistik.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "karambaToSofistik", "karambaToSofistik\karambaToSofistik.csproj", "{40482D48-1CEA-4D7F-A68A-3BF7C27C9B39}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug64|Any CPU = Debug64|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {40482D48-1CEA-4D7F-A68A-3BF7C27C9B39}.Debug64|Any CPU.ActiveCfg = Debug64|Any CPU 15 | {40482D48-1CEA-4D7F-A68A-3BF7C27C9B39}.Debug64|Any CPU.Build.0 = Debug64|Any CPU 16 | {40482D48-1CEA-4D7F-A68A-3BF7C27C9B39}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {40482D48-1CEA-4D7F-A68A-3BF7C27C9B39}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Classes/Beam.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | namespace karambaToSofistik.Classes { 8 | class Beam { 9 | public int id; 10 | public string user_id; 11 | public List ids; 12 | public Node start; 13 | public Node end; 14 | public CrossSection sec; 15 | public Color color; 16 | 17 | public Beam(Karamba.Elements.ModelElement beam = null) { 18 | id = 1; 19 | ids = new List(); 20 | user_id = ""; 21 | start = end = new Node(); 22 | sec = new CrossSection(); 23 | color = new Color(); 24 | 25 | if (beam != null) 26 | hydrate(beam); 27 | } 28 | 29 | public void hydrate(Karamba.Elements.ModelElement beam) { 30 | id = beam.ind + 1; // Sofistik begins at 1 not 0 31 | ids = beam._node_inds; 32 | user_id = beam.id; 33 | 34 | if (!karambaToSofistikComponent.beam_groups.Contains(beam.id)) 35 | karambaToSofistikComponent.beam_groups.Add(beam.id); 36 | 37 | color = beam.color; 38 | } 39 | 40 | public string sofistring() { 41 | return "BEAM NO " + id + " NA " + start.id + " NE " + end.id + " NCS " + sec.id; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using Rhino.PlugIns; 5 | 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("karambaToSofistik")] 11 | [assembly: AssemblyDescription("Converts a Karamba Model to a readable .dat file for Sofistik.")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("UPM")] 14 | [assembly: AssemblyProduct("karambaToSofistik")] 15 | [assembly: AssemblyCopyright("Copyright © 2014")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("d61ffb21-d3cc-42b9-b162-3dd3ffe12f12")] // This will also be the Guid of the Rhino plug-in 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | [assembly: AssemblyVersion("1.0.0.0")] 38 | [assembly: AssemblyFileVersion("1.0.0.0")] 39 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Classes/Node.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace karambaToSofistik.Classes { 8 | class Node { 9 | public int id; 10 | public double x, y, z; 11 | public List constraints; 12 | 13 | public Node(Karamba.Nodes.Node node = null) { 14 | id = 1; 15 | x = y = z = 0; 16 | constraints = new List(); 17 | 18 | if (node != null) 19 | hydrate(node); 20 | } 21 | 22 | public void hydrate(Karamba.Nodes.Node node) { 23 | x = Math.Round(node.pos.X, 3); 24 | y = Math.Round(node.pos.Y, 3); 25 | z = Math.Round(node.pos.Z, 3); 26 | id = node.ind + 1; // Sofistik begins at 1 not 0 27 | } 28 | 29 | public string sofistring() { 30 | string sofi = ""; 31 | sofi += "NODE NO " + id + " X " + x 32 | + " Y " + y 33 | + " Z " + z; 34 | 35 | if (constraints.Count != 0) { 36 | sofi += " FIX "; 37 | 38 | foreach (string condition in constraints) { 39 | if (!Regex.IsMatch(sofi, condition, RegexOptions.IgnoreCase)) 40 | sofi += condition; 41 | } 42 | } 43 | 44 | return sofi; 45 | } 46 | 47 | public void addConstraint(Karamba.Supports.Support support) { 48 | string[] cons = new string[] {"PX", "PY", "PZ", "MX", "MY", "MZ"}; 49 | int i = 0; 50 | 51 | foreach(bool boolean in support._condition) { 52 | if(boolean) 53 | constraints.Add(cons[i]); 54 | // TODO: prescribed displacement 55 | i++; 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Source/karambaToSofistik/Classes/Material.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace karambaToSofistik.Classes { 7 | class Material { 8 | public int id; 9 | public List ids; // Elements to apply to 10 | public double E, G, gamma, alphaT, fy; 11 | string name; 12 | 13 | public Material(Karamba.Materials.FemMaterial material = null) { 14 | ids = new List(); 15 | id = 1; 16 | E = G 17 | = gamma 18 | = alphaT 19 | = fy 20 | = 0; 21 | name = ""; 22 | 23 | if (material != null) 24 | hydrate(material); 25 | } 26 | 27 | public void hydrate(Karamba.Materials.FemMaterial material) { 28 | id = (int) material.ind; // We do not add 1 as for other elements because the first material being corrupted we need to delete it, i.e starting id counting 1 lower. id + 1 - 1 = id. 29 | ids = material.elemIds; 30 | E = Math.Round(material.E / 1000, 3); 31 | G = Math.Round(material.G / 1000, 3); 32 | gamma = Math.Round(material.gamma, 3); 33 | alphaT = Math.Round(material.alphaT, 3); 34 | fy = Math.Round(material.fy / 1000, 3); 35 | name = material.name; 36 | } 37 | 38 | public string sofistring() { 39 | // We need not to forget ton convert into units used by Sofistik 40 | return "STEE NO " + id + " ES " + E 41 | + " GAM " + gamma 42 | + " ALFA " + alphaT 43 | + " GMOD " + G 44 | + " FY " + fy; 45 | } 46 | 47 | //Check if "test" is a duplicate of this material - necessary because karamba adds preset materials 48 | public bool duplicate(Material test) { 49 | if(E == test.E 50 | && G == test.G 51 | && gamma == test.gamma 52 | && alphaT == test.alphaT 53 | && fy == test.fy 54 | ) { 55 | ids.AddRange(test.ids); 56 | return true; 57 | } 58 | return false; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | karambaToSofistik 2 | ============ 3 | 4 | A Grasshopper plugin which takes a Karamba Model and converts it to a .dat file readable by Sofistik. 5 | 6 | Features 7 | -------- 8 | 9 | - Takes as input a Karamba model and outputs a .dat file into CADINPUT language; 10 | - Converts beams, materials, cross sections and loads; 11 | - Covered cross sections types: box profile, circular, I profile, trapezoidal; 12 | - Covered load types: line-load, point load, gravity, pretension, temperature load; 13 | - Takes Grasshopper's ID system into account. 14 | 15 | Installation 16 | ------------ 17 | To install the plugin follow these steps : 18 | 19 | - [Download the plugin][1]. 20 | - Place the GHA file into your plugin directory in Grasshopper. You may find it in *"%APPDATA%\Grasshopper\Libraries"*. 21 | 22 | > **NOTE:** 23 | > 24 | > To find the *%APPDATA%* folder just open the **Run** window (hit WIN+R) then type *"%APPDATA%"* and then OK. 25 | 26 | 27 | Usage 28 | ----- 29 | 30 | This component is very simple to use. You can find it in the Karamba tab in the section "Extra". You have to plug in an input model, that's all! 31 | 32 | You will get the data with "Output". 33 | The "Status" output is for debugging purposes. 34 | 35 | Optionnaly, you can set a input path: **the .dat file will be automatically saved and updated to this location**. 36 | 37 | > **NOTE** 38 | > 39 | > The directoy must exist in order to save the file into it. 40 | 41 | ![Usage demonstration][2] 42 | 43 | *A simple use of this component* 44 | 45 | 46 | 47 | Building it from source 48 | ----------------------- 49 | 50 | As an alternative you can build this plugin from the source and tweak the code if you want. 51 | You will need **Microsoft Visual Studio** with the [Grasshopper Assembly][3] (you can download it directly from Visual Studio in *"Tools > Extensions and updates..."*). 52 | 53 | - Either [download the source zip][4] or fork the repo. 54 | - Open the *Source/karambaToSofistik.sln* project file with Visual Studio. 55 | - In the project tree **check that all the references are available**. If not, fix them (the required libraries can be found in the *Source/Libraries/* directory). 56 | - Build the solution **(Ctrl+Shift+B)**. You should get the GHA file in the *Source/bin* folder. 57 | 58 | > **NOTE** 59 | > 60 | > Visual Studio may give you a warning which says that it can't copy the GHA file to the Grasshopper plugin directory. To change this, edit the project properties and go to **Build Events**. 61 | > 62 | > Replace these lines: 63 | > 64 | > `Copy "$(TargetDir)$(ProjectName).gha" "C:\Users\alberic\AppData\Roaming\Grasshopper\Libraries"` 65 | > `Copy "$(TargetDir)$(ProjectName).gha" "E:\karambaToSofistik\Bin"` 66 | > 67 | > With this one: 68 | > 69 | > `Copy "$(TargetDir)$(ProjectName).gha" "YOUR\GRASSHOPPER\PLUGIN\DIRECTORY"` 70 | > 71 | > With this setup, it will not have to copy again and again the GHA file with every build. 72 | 73 | 74 | [1]: https://github.com/AlbericTrancart/karambaToSofistik/blob/master/Bin/karambaToSofistik.gha?raw=true 75 | [2]: http://image.noelshack.com/fichiers/2014/27/1404381095-capture-2.png "Usage demonstration" 76 | [3]: http://visualstudiogallery.msdn.microsoft.com/9e389515-0719-47b4-a466-04436b491cd6 "Grasshopper Assembly" 77 | [4]: https://github.com/AlbericTrancart/karambaToSofistik/archive/master.zip 78 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Resource.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18408 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace karambaToSofistik { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resource { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resource() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("karambaToSofistik.Resource", typeof(Resource).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Icon { 67 | get { 68 | object obj = ResourceManager.GetObject("Icon", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/karambaToSofistik.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug64 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {40482D48-1CEA-4D7F-A68A-3BF7C27C9B39} 9 | Library 10 | Properties 11 | karambaToSofistik 12 | karambaToSofistik 13 | v4.0 14 | 512 15 | false 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\ 23 | DEBUG;TRACE 24 | prompt 25 | false 26 | 27 | 28 | pdbonly 29 | true 30 | bin\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | False 38 | Libraries\GH_IO.dll 39 | False 40 | 41 | 42 | False 43 | Libraries\Grasshopper.dll 44 | False 45 | 46 | 47 | Libraries\karamba.gha 48 | False 49 | 50 | 51 | 52 | 53 | 54 | 55 | False 56 | Libraries\RhinoCommon.dll 57 | False 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | True 72 | True 73 | Resource.resx 74 | 75 | 76 | 77 | 78 | ResXFileCodeGenerator 79 | Resource.Designer.cs 80 | 81 | 82 | 83 | 84 | 85 | 86 | 93 | 94 | Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha" 95 | Erase "$(TargetPath)" 96 | Copy "$(TargetDir)$(ProjectName).gha" "C:\Users\alberic\AppData\Roaming\Grasshopper\Libraries" 97 | Copy "$(TargetDir)$(ProjectName).gha" "E:\karambaToSofistik\Bin" 98 | 99 | 100 | en-US 101 | 102 | 103 | C:\Program Files\Rhinoceros 5.0 Beta (64-bit)\System\Rhino.exe 104 | 105 | 106 | Program 107 | 108 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Classes/Load.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Rhino.Geometry; 6 | 7 | namespace karambaToSofistik.Classes { 8 | class Load { 9 | public int id; 10 | public Beam beam; // Element to apply to for element load 11 | public string beam_id; 12 | public int orientation; // Local (0), global (1) or projeted (2) orientation for element loads 13 | public Node node; // For Point Loads 14 | public string type; // Valid types are "G, P, E" for Gravity, Point and Element Load 15 | public Vector3d force; 16 | public double coef; // For pretension and temperature loads 17 | 18 | 19 | public void init(string par_type) { 20 | type = par_type; 21 | beam = new Beam(); 22 | node = new Node(); 23 | id = 1; 24 | coef = 0; 25 | force = new Vector3d(); 26 | } 27 | 28 | public Load() { init(""); } 29 | public Load(KeyValuePair load) { init("G"); hydrate(load.Value); } 30 | public Load(Karamba.Loads.PointLoad load) { init("P"); hydrate(load); } 31 | public Load(Karamba.Loads.UniformlyDistLoad load) { init("E"); hydrate(load); } 32 | public Load(Karamba.Loads.PreTensionLoad load) { init("S"); hydrate(load); } 33 | public Load(Karamba.Loads.TemperatureLoad load) { init("T"); hydrate(load); } 34 | 35 | public void hydrate(Karamba.Loads.GravityLoad load) { 36 | force = load.force; 37 | } 38 | 39 | public void hydrate(Karamba.Loads.PointLoad load) { 40 | force = load.force; 41 | } 42 | 43 | public void hydrate(Karamba.Loads.UniformlyDistLoad load) { 44 | orientation = (int) load.q_orient; 45 | beam_id = load.beamId; 46 | force = load.Load; 47 | } 48 | 49 | public void hydrate(Karamba.Loads.PreTensionLoad load) { 50 | beam_id = load.beamId; 51 | coef = Math.Round(load.EPS0, 3); 52 | } 53 | 54 | public void hydrate(Karamba.Loads.TemperatureLoad load) { 55 | beam_id = load.beamId; 56 | coef = Math.Round(load.incT, 3); 57 | } 58 | 59 | public string sofistring() { 60 | id = Parser.id_count; 61 | Parser.id_count++; 62 | 63 | switch (type) { 64 | case "G": 65 | return "LC NO " + id + " TYPE P\nBEAM FROM 1 TO 999999 TYPE PXX,PYY,PZZ" 66 | + " PA " + Math.Round(force.X, 3) 67 | + "," + Math.Round(force.Y, 3) 68 | + "," + Math.Round(force.Z, 3); 69 | case "P": 70 | return "LC NO " + id + " TYPE L\nNODE NO " + node.id 71 | + " TYPE PP" 72 | + " P1 " + Math.Round(force.X, 3) 73 | + " P2 " + Math.Round(force.Y, 3) 74 | + " P3 " + Math.Round(force.Z, 3); 75 | case "E": 76 | case "S": 77 | case "T": 78 | string from = ""; 79 | if (beam_id == "") 80 | from = "1 TO 999999"; 81 | else 82 | from = "GRP " + karambaToSofistikComponent.beam_groups.IndexOf(beam_id); 83 | 84 | if (type == "E") { 85 | string load_type = ""; 86 | if (orientation == 0) 87 | load_type = "PX,PY,PZ"; 88 | else if (orientation == 2) 89 | load_type = "PXP,PYP,PZP"; 90 | else 91 | load_type = "PXX,PYY,PZZ"; 92 | 93 | return "LC NO " + id + " TYPE L\nBEAM FROM " + from 94 | + " TYPE " + load_type 95 | + " PA " + Math.Round(force.X, 3) 96 | + "," + Math.Round(force.Y, 3) 97 | + "," + Math.Round(force.Z, 3); 98 | } 99 | else if(type == "S") { 100 | return "LC NO " + id + " TYPE L\nBEAM FROM " + from 101 | + " TYPE PNX PA " + coef; 102 | } 103 | else if (type == "T") { 104 | return "LC NO " + id + " TYPE L\nBEAM FROM " + from 105 | + " TYPE TEMP PA " + coef; 106 | } 107 | break; 108 | } 109 | return ""; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Classes/Parser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace karambaToSofistik.Classes { 7 | class Parser { 8 | static public int id_count = 1; // Karamba does not provide IDs for loads so we must create one 9 | public string file { get; protected set; } 10 | 11 | public Parser(List materials, List crossSections, List nodes, List beams, List loads) { 12 | file = ""; 13 | 14 | // AQUA definitions 15 | file += "+PROG AQUA urs:1\nHEAD Material and cross section definitions\nUNIT 5\n\n"; 16 | 17 | foreach (Material material in materials) { 18 | if(material.sofistring() != "") 19 | file += material.sofistring() + "\n"; 20 | } 21 | file += "\n"; 22 | foreach (CrossSection crossSection in crossSections) { 23 | if (crossSection.sofistring() != "") 24 | file += crossSection.sofistring() + "\n"; 25 | } 26 | 27 | // SOFIMSHA definitions 28 | file += "\nEND\n\n\n+PROG SOFIMSHA urs:2\nHEAD Elements\nUNIT 5\nSYST TYPE 3D GDIR NEGZ GDIV 1000\n\n"; 29 | 30 | foreach (Node node in nodes) { 31 | file += node.sofistring() + "\n"; 32 | } 33 | 34 | // Special addition of beam: we must define groups 35 | int cluster_start, node_start, node_end, crosec; 36 | cluster_start = node_start = node_end = crosec = 1; 37 | int iterator = 0; 38 | Beam last_beam = new Beam(); 39 | 40 | foreach (string group in karambaToSofistikComponent.beam_groups) { 41 | if (karambaToSofistikComponent.beam_groups.Count > 0) { 42 | file += "\nGRP " + karambaToSofistikComponent.beam_groups.IndexOf(group) + ";\n"; 43 | iterator = 0; 44 | 45 | foreach (Beam beam in beams) { 46 | //Initiate first beam 47 | if (last_beam == new Beam()) 48 | last_beam = beam; 49 | 50 | // Output one group after the other 51 | if (beam.user_id == group) { 52 | // Beams are automatically ordered by their ID, therefore it is simple to clear the syntax by defining them in cluster 53 | if (iterator == 0) { 54 | // Start a new cluster 55 | cluster_start = beam.id; 56 | node_start = beam.start.id; 57 | node_end = beam.end.id; 58 | crosec = beam.sec.id; 59 | iterator = 1; 60 | last_beam = beam; 61 | continue; 62 | } 63 | 64 | // Check if we are moving into another cluster 65 | if (beam.id != cluster_start + iterator 66 | || beam.start.id != node_start + iterator 67 | || beam.end.id != node_end + iterator 68 | || beam.sec.id != crosec) { 69 | 70 | // End the cluster and print it 71 | if (iterator == 1) { 72 | // Normal beam 73 | file += last_beam.sofistring() + "\n"; 74 | } 75 | else { 76 | // Clusterized definition 77 | file += "BEAM NO (" + cluster_start + " " + (cluster_start + iterator - 1) + " 1)" 78 | + " NA (" + node_start + " 1)" 79 | + " NE (" + node_end + " 1)" 80 | + " NCS " + crosec + "\n"; 81 | } 82 | 83 | // Start a new cluster 84 | cluster_start = beam.id; 85 | node_start = beam.start.id; 86 | node_end = beam.end.id; 87 | crosec = beam.sec.id; 88 | iterator = 1; 89 | last_beam = beam; 90 | continue; 91 | } 92 | else { 93 | iterator++; 94 | last_beam = beam; 95 | } 96 | } 97 | } 98 | 99 | // Print the last cluster 100 | if (iterator == 1) { 101 | // Normal beam 102 | file += last_beam.sofistring() + "\n"; 103 | } 104 | else { 105 | // Clusterized definition 106 | file += "BEAM NO (" + cluster_start + " " + (cluster_start + iterator - 1) + " 1)" 107 | + " NA (" + node_start + " 1)" 108 | + " NE (" + node_end + " 1)" 109 | + " NCS " + crosec + "\n"; 110 | } 111 | } 112 | } 113 | 114 | // SOFILOAD definitions 115 | file += "\n\n+PROG SOFILOAD urs:4\nHEAD Loads\nUNIT 5\n\n"; 116 | foreach (Load load in loads) { 117 | file += load.sofistring() + "\n"; 118 | } 119 | 120 | // Analysis 121 | file += "\nEND\n\n\n+PROG ASE urs:13\nHEAD Solving\n\nSYST PROB LINE\nLC ALL\n\nEND\n"; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Resource.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /Source/karambaToSofistik/Classes/CrossSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace karambaToSofistik.Classes { 7 | class CrossSection { 8 | public int id; 9 | public List ids; // Elements to apply to 10 | public string shape; // Available: O, [], V, I 11 | public double diameter, thickness, height, 12 | upperWidth, lowerWidth, upperThick, lowerThick, 13 | sWallThick, webThick, filletRadius; 14 | public string name; 15 | public Material material; 16 | 17 | public CrossSection(Karamba.CrossSections.CroSec crosec = null) { 18 | id = 1; 19 | ids = new List(); 20 | shape = ""; 21 | name = ""; 22 | material = new Material(); 23 | diameter = thickness 24 | = height 25 | = upperWidth 26 | = lowerWidth 27 | = upperThick 28 | = lowerThick 29 | = sWallThick 30 | = webThick 31 | = filletRadius 32 | = 0; 33 | 34 | if(crosec != null) 35 | hydrate(crosec); 36 | } 37 | 38 | public void hydrate(Karamba.CrossSections.CroSec crosec) { 39 | id = (int) crosec.ind + 1; // Sofistik begins at 1 not 0 40 | ids = crosec.elemIds; 41 | name = crosec.name; 42 | shape = crosec.shape(); 43 | 44 | if (shape == "V") { 45 | height = Math.Round((double) crosec.dims[0] * 1000, 3); 46 | upperWidth = Math.Round((double) crosec.dims[2] * 1000, 3); 47 | lowerWidth = Math.Round((double) crosec.dims[4] * 1000, 3); 48 | } 49 | else if (shape == "O") { 50 | diameter = Math.Round((double) crosec.dims[0] * 1000, 3); 51 | thickness = Math.Round((double) crosec.dims[1] * 1000, 3); 52 | } 53 | else if (shape == "[]") { 54 | height = Math.Round((double) crosec.dims[0] * 1000, 3); 55 | sWallThick = Math.Round((double) crosec.dims[1] * 1000, 3); 56 | upperWidth = Math.Round((double) crosec.dims[2] * 1000, 3); 57 | upperThick = Math.Round((double) crosec.dims[3] * 1000, 3); 58 | lowerWidth = Math.Round((double) crosec.dims[4] * 1000, 3); 59 | lowerThick = Math.Round((double) crosec.dims[5] * 1000, 3); 60 | filletRadius = Math.Round((double) crosec.dims[6] * 1000, 3); 61 | } 62 | else if (shape == "I") { 63 | height = Math.Round((double) crosec.dims[0] * 1000, 3); 64 | webThick = Math.Round((double) crosec.dims[1] * 1000, 3); 65 | upperWidth = Math.Round((double) crosec.dims[2] * 1000, 3); 66 | upperThick = Math.Round((double) crosec.dims[3] * 1000, 3); 67 | lowerWidth = Math.Round((double) crosec.dims[4] * 1000, 3); 68 | lowerThick = Math.Round((double) crosec.dims[5] * 1000, 3); 69 | filletRadius = Math.Round((double) crosec.dims[6] * 1000, 3); 70 | } 71 | } 72 | 73 | public string sofistring() { 74 | // Sofistik wants millimeters 75 | if (shape == "V") { 76 | return "SECT " + id + " MNO " + material.id 77 | + "\nPLAT NO 1 YB " + (-upperWidth / 2) 78 | + " ZB " + height 79 | + " YE " + (upperWidth / 2) 80 | + " ZE " + height 81 | + " T 10" 82 | + "\nNO 2 YB " + (upperWidth / 2) 83 | + " ZB " + height 84 | + " YE " + (upperWidth / 2) 85 | + " ZE " + 0 86 | + " T 10" 87 | + "\nNO 3 YB " + (upperWidth / 2) 88 | + " ZB " + 0 89 | + " YE " + (-upperWidth / 2) 90 | + " ZE " + 0 91 | + " T 10" 92 | + "\nNO 4 YB " + (-upperWidth / 2) 93 | + " ZB " + 0 94 | + " YE " + (-upperWidth / 2) 95 | + " ZE " + height 96 | + " T 10"; 97 | } 98 | else if (shape == "O") { 99 | return "TUBE " + id + " MNO " + material.id 100 | + " D " + diameter 101 | + " T " + thickness; 102 | } 103 | else if (shape == "[]") { 104 | return "SREC " + id + " MNO " + material.id 105 | + " H " + height 106 | + " HO " + Math.Max(lowerThick, upperThick) 107 | + " B " + lowerWidth 108 | + " BO " + upperWidth; 109 | } 110 | else if (shape == "I") { 111 | return "SECT " + id + " MNO " + material.id 112 | + "\nPLAT NO 1 YB " + (-upperWidth / 2) 113 | + " ZB " + (height - upperThick / 2) 114 | + " YE " + 0 115 | + " ZE " + (height - upperThick / 2) 116 | + " T " + upperThick 117 | + "\nNO 2 YB " + 0 118 | + " ZB " + (height - upperThick / 2) 119 | + " YE " + (upperWidth / 2) 120 | + " ZE " + (height - upperThick / 2) 121 | + " T " + upperThick 122 | + "\nNO 3 YB " + 0 123 | + " ZB " + (height - upperThick / 2) 124 | + " YE " + 0 125 | + " ZE " + (lowerThick / 2) 126 | + " T " + webThick 127 | + "\nNO 4 YB " + (-lowerWidth / 2) 128 | + " ZB " + (lowerThick / 2) 129 | + " YE " + 0 130 | + " ZE " + (lowerThick / 2) 131 | + " T " + lowerThick 132 | + "\nNO 5 YB " + 0 133 | + " ZB " + (lowerThick / 2) 134 | + " YE " + (lowerWidth / 2) 135 | + " ZE " + (lowerThick / 2) 136 | + " T " + lowerThick; 137 | } 138 | return ""; 139 | } 140 | 141 | // Check if "test" is a duplicate of this cross section - necessary because karamba adds preset cross sections 142 | public bool duplicate(CrossSection test) { 143 | if (shape == "V") { 144 | if (height == test.height && lowerWidth == test.lowerWidth && upperWidth == test.upperWidth) { 145 | ids.AddRange(test.ids); 146 | return true; 147 | } 148 | } 149 | else if (shape == "O") { 150 | if (diameter == test.diameter && thickness == test.thickness) { 151 | ids.AddRange(test.ids); 152 | return true; 153 | } 154 | } 155 | else if (shape == "[]") { 156 | if ( 157 | height == test.height 158 | && sWallThick == test.sWallThick 159 | && filletRadius == test.filletRadius 160 | && upperWidth == test.upperWidth 161 | && lowerWidth == test.lowerWidth 162 | && upperThick == test.upperThick 163 | && lowerThick== test.lowerThick 164 | ) { 165 | ids.AddRange(test.ids); 166 | return true; 167 | } 168 | } 169 | else if (shape == "I") { 170 | if ( 171 | height == test.height 172 | && webThick == test.webThick 173 | && filletRadius == test.filletRadius 174 | && upperWidth == test.upperWidth 175 | && lowerWidth == test.lowerWidth 176 | && upperThick == test.upperThick 177 | && lowerThick == test.lowerThick 178 | ) { 179 | ids.AddRange(test.ids); 180 | return true; 181 | } 182 | } 183 | return false; 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /Source/karambaToSofistik/karambaToSofistikComponent.cs: -------------------------------------------------------------------------------- 1 | // Karamba To Sofistik component for GrassHopper 2 | // Convert a karamba model to a .dat file readable by Sofistik 3 | // Git: https://github.com/AlbericTrancart/karambaToSofistik 4 | // Contact: alberic.trancart@eleves.enpc.fr 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | 10 | using Grasshopper.Kernel; 11 | using Rhino.Geometry; 12 | 13 | using Karamba.Models; 14 | using Karamba.Elements; 15 | 16 | using karambaToSofistik.Classes; 17 | 18 | namespace karambaToSofistik { 19 | public class karambaToSofistikComponent : GH_Component { 20 | // Component configuration 21 | public karambaToSofistikComponent() : base("karambaToSofistik", "ktS", "Converts a Karamba model to a .dat file readable by Sofistik", "Karamba", "Extra") { } 22 | 23 | // Registers all the input parameters for this component. 24 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) { 25 | pManager.AddParameter(new Param_Model(), "Model", "Model", "Model to convert", GH_ParamAccess.item); 26 | pManager.AddTextParameter("Path", "Path", "Save the .dat file to this path", GH_ParamAccess.item, @""); 27 | } 28 | 29 | // Registers all the output parameters for this component. 30 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { 31 | pManager.Register_StringParam("Output", "Output", "Converted model"); 32 | pManager.Register_StringParam("Status", "Status", "Errors or success messages"); 33 | } 34 | 35 | // We need to register all groups defined in Grasshopper 36 | static public List beam_groups = new List(); 37 | 38 | // This is the method that actually does the work. 39 | protected override void SolveInstance(IGH_DataAccess DA) { 40 | // Some variables 41 | string output = ""; // The file output 42 | string status = "Starting component...\n"; // The debug output 43 | 44 | // Several arrays where the data is stored 45 | List materials = new List(); 46 | List crossSections = new List(); 47 | List nodes = new List(); 48 | List beams = new List(); 49 | List loads = new List(); 50 | 51 | // We need to reset some variables because the objects are not freed until Grasshopper is unloaded 52 | Parser.id_count = 1; 53 | 54 | try { 55 | // Load the data from Karamba 56 | 57 | // Retrieve and clone the input model 58 | GH_Model in_gh_model = null; 59 | if (!DA.GetData(0, ref in_gh_model)) return; 60 | Model model = in_gh_model.Value; 61 | model = (Karamba.Models.Model) model.Clone(); // If the model is not cloned a modification to this variable will imply modification of the input model, thus modifying behavior in other components. 62 | 63 | if (model == null) { 64 | status += "ERROR: The input model is null."; 65 | output = "Nothing to convert"; 66 | } 67 | else { 68 | string path = null; 69 | if (!DA.GetData(1, ref path)) { path = ""; } 70 | if (path == "") { 71 | status += "No file path specified. Will not save data to a .dat file.\n"; 72 | } 73 | 74 | 75 | 76 | // Retrieve and store the data 77 | 78 | // Materials 79 | foreach (Karamba.Materials.FemMaterial material in model.materials) { 80 | // The first material seems to be wong but I don't know why it exists 81 | if(model.materials.IndexOf(material) != 0) 82 | materials.Add(new Material(material)); 83 | } 84 | 85 | /*Disabled for forward compatibility 86 | // Check for material duplicates 87 | // This is necessary because karamba uses a preset material that is added every time that a model is assembled 88 | // As a consequence a model can get a great amount of redundant materials that will flood the output 89 | 90 | // Furthermore karamba seems to create a buggy material at index 0 during the cloning operation 91 | materials.RemoveAt(0); 92 | // Using a for loop because a collection used in foreach is immutable 93 | for (int i = 0; i < materials.Count; i++) { 94 | materials.RemoveAll(delegate(Material test_material) { 95 | return test_material.id != materials[i].id && materials[i].duplicate(test_material); 96 | }); 97 | } 98 | */ 99 | status += materials.Count + " materials loaded...\n"; 100 | 101 | 102 | 103 | // Cross sections 104 | foreach (Karamba.CrossSections.CroSec crosec in model.crosecs) { 105 | crossSections.Add(new CrossSection(crosec)); 106 | } 107 | /*Disabled for forward compatibility 108 | // The same happens with Cross Sections 109 | crossSections.RemoveAt(0); 110 | for (int i = 0; i < crossSections.Count; i++) { 111 | crossSections.RemoveAll(delegate(CrossSection test_crosec) { 112 | return test_crosec.id != crossSections[i].id && crossSections[i].duplicate(test_crosec); 113 | }); 114 | } 115 | status += crossSections.Count + " cross sections loaded...\n"; 116 | */ 117 | 118 | 119 | // Nodes 120 | foreach (Karamba.Nodes.Node node in model.nodes) { 121 | nodes.Add(new Node(node)); 122 | } 123 | status += nodes.Count + " nodes loaded...\n"; 124 | 125 | foreach (Karamba.Supports.Support support in model.supports) { 126 | nodes[support.node_ind].addConstraint(support); 127 | } 128 | status += "Support constraints added to " + model.supports.Count + " nodes.\n"; 129 | 130 | 131 | 132 | // Beams 133 | foreach (Karamba.Elements.ModelElement beam in model.elems) { 134 | Beam curBeam = new Beam(beam); 135 | 136 | // Adding the start and end nodes 137 | curBeam.start = nodes[curBeam.ids[0]]; 138 | curBeam.end = nodes[curBeam.ids[1]]; 139 | beams.Add(curBeam); 140 | } 141 | status += beams.Count + " beams loaded...\n"; 142 | 143 | 144 | 145 | // Loads 146 | foreach (KeyValuePair load in model.gravities) { 147 | loads.Add(new Load(load)); 148 | } 149 | status += model.gravities.Count + " gravity loads added.\n"; 150 | 151 | foreach (Karamba.Loads.PointLoad load in model.ploads) { 152 | Load current = new Load(load); 153 | current.node = nodes[load.node_ind]; 154 | loads.Add(current); 155 | } 156 | status += model.ploads.Count + " point loads added.\n"; 157 | 158 | foreach (Karamba.Loads.ElementLoad load in model.eloads) { 159 | // Create a load variable base on the load type 160 | Load current = new Load(); 161 | 162 | Karamba.Loads.UniformlyDistLoad line = load as Karamba.Loads.UniformlyDistLoad; 163 | Karamba.Loads.PreTensionLoad pret = load as Karamba.Loads.PreTensionLoad; 164 | Karamba.Loads.TemperatureLoad temp = load as Karamba.Loads.TemperatureLoad; 165 | 166 | if (line != null) { 167 | current = new Load(line); 168 | } 169 | // Very important to check Temperature BEFORE Pretension becaus Temperature derivates from Pretension 170 | else if (temp != null) { 171 | current = new Load(temp); 172 | } 173 | else if (pret != null) { 174 | current = new Load(pret); 175 | } 176 | 177 | 178 | // If there is not target element, apply the load to the whole structure 179 | if (load.beamId == "") { 180 | current.beam_id = ""; 181 | loads.Add(current); 182 | } 183 | else { 184 | // We search the element 185 | current.beam = beams.Find(delegate(Beam beam) { 186 | return beam.user_id == load.beamId; 187 | }); 188 | loads.Add(current); 189 | } 190 | } 191 | 192 | status += model.eloads.Count + " line loads added.\n"; 193 | 194 | // ID matching 195 | // Karamba and Sofistik use different ID systems 196 | // Karamba's materials and cross sections are pointing to an element ID 197 | // Sofistik's elements need a cross section ID which needs a material ID 198 | 199 | foreach (Material material in materials){ 200 | // If the IDs list is empty, it means that we want to apply the material to the whole structure (whichi is the default behavior: the default material is set by the constructors of all elements) 201 | bool test = false; 202 | foreach (string id in material.ids) { 203 | if(id != "") 204 | test = true; 205 | } 206 | if (test) { 207 | foreach (CrossSection crosec in crossSections) { 208 | if(material.ids.Contains((crosec.id - 1).ToString())) 209 | crosec.material = material; 210 | } 211 | } 212 | } 213 | status += "Matching with material IDs...\n"; 214 | 215 | foreach (CrossSection crosec in crossSections) { 216 | // If the IDs list is empty, it means that we want to apply the cross section to the whole structure (which is the default behavior: the default cross section is set by the constructors of all elements) 217 | bool test = false; 218 | foreach (string id in crosec.ids) { 219 | if (id != "") 220 | test = true; 221 | } 222 | if (test) { 223 | foreach (Beam beam in beams) { 224 | if (crosec.ids.Contains((beam.id - 1).ToString())) 225 | beam.sec = crosec; 226 | } 227 | } 228 | } 229 | status += "Matching with cross section IDs...\n"; 230 | 231 | // Write the data into a .dat file format 232 | Parser parser = new Parser(materials, crossSections, nodes, beams, loads); 233 | output = parser.file; 234 | 235 | if (path != "") { 236 | status += "Saving file to " + path + "\n"; 237 | System.IO.File.WriteAllText(@path, output); 238 | status += "File saved!\n"; 239 | } 240 | } 241 | } 242 | catch (Exception e) { 243 | status += "\nERROR!\n" + e.ToString() + "\n" + e.Data; 244 | } 245 | 246 | // Return data 247 | DA.SetData(0, output); 248 | DA.SetData(1, status); 249 | } 250 | 251 | // Icon 252 | protected override System.Drawing.Bitmap Icon { 253 | get { return Resource.Icon; } 254 | } 255 | 256 | // Each component must have a unique Guid to identify it. 257 | public override Guid ComponentGuid { 258 | get { return new Guid("{1954a147-f7a2-4d9c-b150-b788821ccae7}"); } 259 | } 260 | } 261 | } 262 | --------------------------------------------------------------------------------