2.5: Data Export from Karamba3D

When it comes to exporting data from a Karamba3D model to another data-format one could simply go through the object tree of the model and iterate manually over the existing entities like e.g. nodes, elements, materials, . . . . The use of a builder pattern removes some of the bureaucratic overhead involved in this approach. The script in the example “ModelExport.gh” shows how to generate an XML-file based on a given Karamba3D-model. The output consists of a string which can be streamed to a file. When opened with a web-browser a nicely formatted tree results (see fig. 2.5.1).

By inheriting from "Karamba.Exporters.ExportBuilder" and overriding "builder"-methods a builder-class can be configured to export Karamba3D-models to any format - here XML.

The corresponding source-code looks like this:

...
using System.Xml;
using System.IO;
using Karamba.Models;
using Karamba.Nodes;
using Karamba.CrossSections;
using Karamba.Elements;
using Karamba.Loads;
using Karamba.Materials;
using Karamba.Supports;
using Karamba.Geometry;
...
private void RunScript(object Model_in, ref object XML)
{
    var model = Model_in as Model;
    if (model == null) {
      throw new ArgumentException("The input is not of type model!");
    }

    var builder = new BuilderXML();
    var director = new Karamba.Exporters.ExportDirector();
    director.ConstructExport(model, builder);

    XML = builder.getProduct();
}

// <Custom additional code>
public class BuilderXML : Karamba.Exporters.ExportBuilder {
  // the XML document
  private XmlDocument doc_ = new XmlDocument();
  // the model inside the xml-document
  private XmlElement model_;

  public override void newProduct() {
    model_ = (XmlElement) doc_.AppendChild(doc_.CreateElement("K3DModel"));
  }

  public override void buildMaterial(FemMaterial m, int ind) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("FemMaterial"));
    xml_node.InnerText = "ind: " + ind + ":" + m.ToString();
  }

  public override void buildVertex(Node v) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("Node"));
    xml_node.InnerText = v.ToString();
  }

  public override void buildCroSec(CroSec crosec) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("CroSec"));
    xml_node.InnerText = crosec.ToString();
  }

  public override void buildElement(ModelElement e, Model model) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("ModelElement"));
    xml_node.InnerText = e.ToString();
  }

  public override void buildElementLoad(ModelElement elem, Model model) {
    foreach (var l in elem.Elem_loads) {
      var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("ElementLoad"));
      xml_node.InnerText = l.ToString();
    }
  }

  public override void buildLoadCase(int lc_ind, Model model) {
    Vector3 g_vec = new Vector3(0, 0, 0);
    foreach (GravityLoad g in model.gravities.Values) {
      if (model.lc_combinator.lc_inds(g.LcName).Contains(lc_ind)) {
        g_vec = g.force;
        };
      }

    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("LoadCase"));
    xml_node.InnerText = "load-case: " + lc_ind + " g =" + g_vec;

  }

  public override void buildSupport(Support s) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("Support"));
    xml_node.InnerText = s.ToString();
  }

  public override void buildPointLoad(PointLoad p) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("PointLoad"));
    xml_node.InnerText = p.ToString();
  }

  public override void buildMeshLoad(MeshLoad m) {
    var xml_node = (XmlElement) model_.AppendChild(doc_.CreateElement("MeshLoad"));
    xml_node.InnerText = m.ToString();
  }

  public string getProduct() {
    StringWriter sw = new StringWriter();
    XmlTextWriter tx = new XmlTextWriter(sw);
    doc_.WriteTo(tx);
    string str = sw.ToString();//
    return str;
  }
}
// </Custom additional code>

The first part of the script comprises the “RunScript”-method. There the “Model_in”-object gets converted to a Karamba3D-Model. In line 20 follows the creation of a builder-object which does the conversion-work. The class “BuilderXML” gets defined further below in the script. A director-object is instantiated in the next line. Its task consists of iterating over the model constituents and presenting them to the builder. Calling “ConstructExport” in line 22 initiates the creation process. Line 24 assigns the builder’s product to the output variable “XML”.

The “BuilderXML”-class derives from Karamba.Exporters.ExportBuilder and overrides some of its methods. In order to keep things simple each build-method adds a XML-node which contains the string-representation of the corresponding argument. In case of “ModelElement” the corresponding build-method does not know which type of element gets passed. Thus one has to apply pattern matching to find get the right type (e.g. “ModelBeam”, “ModelTruss”, “ModelShell” or “ModelSpring”)

Last updated