Questions/remarks on structural objects and their GH implementation

Hi Speckle and Structural Community,

Thanks for the meetup. As mentioned, here is a mix of comments or questions that I have been writing down while I’ve been using the structural object model in combination with SAF. It was a bit too much (and perhaps too detailed) for the meetup.


  • Are there any plans for or thoughts about adding (symbolic) visualisation of structural model objects in the online 3D viewer or Grasshopper (for supports, members, loads, joints, results, cross sections…)?
    Also for elements it could help to understand their final position and orientation (taking into account offsets, eccentricities, alignments, rotation angles, orientation nodes, axes, …).

Missing properties:

  • If for a specific app there are one or two properties missing in a Speckle object which are not always needed (e.g. the fillet radius of a tube section, that needs to be defined in SAF), is it better to add them dynamically (in the member dictionary of the base object) or to make a new app-specific derived class in which these properties are added (better defined, but might lead to a lot of classes in the end)?

Geometry classes:

  • It would be useful to have methods for common geometry operations to deal with local coordinate systems of elements (also see here): vector length, cross/dot product, norm, line direction, …

Element1D class:

  • baseLine property of Element1D should accept a general ICurve instead of a Line; curved or multisegmented beams are imaginable.
  • orientationNode: if specified, this should overrule the Axis property, correct? Since Axis and OrientationNode both handle the Local Coordinate System of an object, better to only store one of both and to let the other property be automatically derived from the first. Would you agree?
  • better to use an OrientationPoint instead of OrientationNode, as only the XYZ coordinate of this object is relevant?
  • another example of duplicate data in properties is baseLine, end1Node, end2Node and topology. Better to for example scratch the end nodes and only use topology (and rename this property to “nodes”)? It will certainly simplify the amount of cases to be considered by converters.
  • Property1D.offsetY and offsetZ values duplicate Element1D end1offset and end2offset?
  • When selecting Element1D objects in the Speckle web viewer, you select the Line object, not the Element1D object, making it difficult to browse their properties; are there plans to correct this?

Axis class:

  • I find axis confusing as a name, something like CoordinateSystem would more clearly represent what it is. Perhaps this is just me?
  • it is currently defined by a plane, not 3 vectors; when set for a 1D element, should this be the plane normal to the element in which the profile is drawn (feels most intuitive; the main axis of a plane tends to be its normal) or should the axes correspond to the local axis convention of a beam (which makes most sense; X along the length of the element, Z points up and Y points right)?

AnalysisModel class:

  • what’s the logic behind the choice of properties, and where should each object type be stored within this model object?
    • for example, should the Loads property only contain loads, or also LoadCases, LoadCombinations, …?
    • restraint doesn’t exist as separate object in SAF, but is always defined in combination with geometry (points, lines, …); the restraints property of the AnalysisModel in this case is thus not useful. What’s the added value of adding it separately?

Loads: common need for a ThermalLoad object?


  • Currently seem very specific for GSA, and it is not always to find a one-on-one mapping with SAF:
    • e.g. Speckle LoadType enum vs. SAF Load Type enum > how would you map these?
    • to make them more open to alternative classifications or definitions, perhaps it is useful to also have a “Other” or “NotDefined” option for each Enum? Currently there are some Null or Undefined or NotDefined options existing, but it might be better to have one for each enum with a consistent name.

Some ideas/questions specific for Grasshopper (as this is a powerful way to define parametric structural models):

  • Is it possible to add a custom string representation to Speckle objects? Or default to “Class name + Name value”. The current one is often not very meaningful for people setting up these models:

  • would it be possible to manually delete or not show some properties in the ExpandSpeckleObject component (e.g. the ones with no value), as there are often many unused ones?

  • also for the ExpandSpeckleObject component, would it be possible to match the order of the most common schema inputs in the output parameters to avoid the spaghetti below?

  • icons in Grasshopper can help navigation and finding the correct schema node. It seems useful to build an icon library (at least for the most common objects) with icons based on namespace + class name:

    • to avoid having to create an icon for each schema object, automatically pick the one with the longest name match. E.g. for Objects.Structural.Geometry.Element1D, first try Objects.Structural.Geometry.Element1D, if not existing try Objects.Structural.Geometry, else try Objects.Structural, else take the basic Objects one

That’s all for the moment. Happy to hear your thoughts and discuss!



Goede morgen Kelvin, I’ll answer on the parts that i’m credible on! I’ll leave the rest to y’all structural folks.

I remember we did discuss this previously, but only for visualising results (e.g., moment diagrams). This can definitively happen though, albeit there’s going to be quite some artistry and threejs-magicness involved. Some points:

  • would be good to have a set of “prior art”, so we can understand how these are usually displayed
  • anything line based is not optimised for display yet, as @cristi didn’t have time yet to look at that, and this might influence a bit how we structure those conversions into threejs objects.

My gut feeling here is to go, at first, with adding them as dynamic props, and being defensive on the conversion toX side (ie, checking if the prop exists and isn’t null before actually using it). We can always cement those props later in actual classes. (why i’m thinking like this: it’s very easy to add props to a class, but it’s very difficult to remove them afterwards)

Why not? I think @Jedd needed some too. I would, though, include them in a separate project, outside of the Object model. B

Oh yeah, i kinda wanted that too for some time. IIRC, the default toString() of a base object returns it’s fully qualified type (by speckle deserialisation standards), but we’re not relying on the toString() method itself. Two options:

  • we decide on a common way to do it in Base, e.g., just use the last, most specific type
  • override it on a class by class basis

The problem is one takes the arguments from the schema info constructor, and ESO just uses alphabetical order. Not sure what the best way would be, perhaps ensuring the schemainfo constructor’s args are in the same alphabetical order? this might not always make sense :thinking:

Over to @Reynold_Chan for the structural parts, and @AlanRynne if you have time, feel free to chime in on the grasshopper parts!


Thanks @dimitrie for your reply!

Great to hear! Karamba3D is a great source of inspiration here.

So it’s not on your own backlog yet? I guess it’s best to integrate an existing library, like

Perhaps we can tag the properties that we want to see appearing in the string representation? So we have a single ToString method in Base of which the contents can be manipulated per object.

We could (again using a tag) add an order to the object fields: c# - Get properties in order of declaration using reflection - Stack Overflow. Question remains whether this is a good idea…

@Reynold_Chan , , @AlanRynne, would be happy to hear your feedback. I’ll make sure to post these kinds of lists BEFORE the meetup next time so it can be discussed there :wink:


1 Like

Hi Kelvin,

Apologies for the late response.

So these kinda go hand in hand. The baseline doesn’t accept a general ICurve , but maybe it should accept a general polyLine at most. I’ve been hesitant toward defining a general ICurve mainly because I think it’s a simplicity factor and mainly cause I don’t recall the last time I saw a curved line being modelled inside FEM programs.

You will probably only use Element1D end1offset, as opposed to property1D offset Y/Z, those offsets are meant more for the property offset themselves for the sections.

So this is cause some program uses plane as well for definition, but I do agree that Node is more common. Need some more thought about this one.

It’s alright ? just a personal preference here I think. Axis makes sense to me because you can have polar .

Yes this is because axis can be non Cartesian in nature. Hence why we would use the orientation node/angle more. I think the logic behind the whole axis thing is due to non-cartesian possibilities.

Fair !

Most of these have 1-1 mappings, but they are always open to more review. I agree that it might be useful to have an Other for all enums.


Hi @Reynold_Chan,

Thanks for your feedback!

Regarding the example use of some properties/objects, are you aware of other community initiatives making use of the Structural objects for new connectors/converters?

In case multiple properties contain the same info but in a different format, would it be better to make one of the properties a function of the other? This to remove duplicate data, which risks to be inconsistent and complicates methods. For example, as a 1D member’s topology also comprising the startNode and endNode, just store those into the topology and return the first item of the topology list when requesting the startNode, and the last when requesting the endNode.

Indeed, it’s not common, but in SCIA for example you can model curved members (whether you should is a different question). If you want to create an object model that can serve any software, I would think that its basis should be as permissive as possible. Afterwards limiting the geometry to lines for some converters is just a simple line of code.