ting at multiple geometries in the same location. I simply sorted the list of values and used the Delete Consecutive component. This potentially rearranges the order of values but I don't think that matters in your case. I also threw in an Int component which actually seems to make a difference (try sidestepping it and you will see!).
2-I flattened the output of the mesh component before sending it to union. This ensures that the original mesh is booleaned once with all the components rather than individually with each of the 86 components.
Is this what the result should look like?
One suggestion for future postings: when referencing geometry in rhino, it often helps if you attach your rhino file as well so people don't have to guess where you are starting from.
If you have further questions, just ask ;-)
cbass…
.
Things have been working swimmingly in many areas of the plugin, but one particular problem has been tough to solve. I have two components that are trying to read/write to the same memory at the same time, causing Rhino exceptions and crashes.
The conflicts appear to be happening between two components -- one is a "Layer Events Listener" that reports essentially what type of layer event just happened. The other is a "Set Layer Visibility" component that toggles the visibility of a list of layers.
The code:
public class LayerTools_LayerEventsListener : GH_Component { /// <summary> /// Initializes a new instance of the LayerTools_LayerListener class. /// </summary> public LayerTools_LayerEventsListener() : base("Layer Events Listener", "Layer Listener", "Get granular information about the layer events happening in the Rhino document.", "Squirrel", "Layer Tools") { }
/// <summary> /// Registers all the input parameters for this component. /// </summary> protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) { pManager.AddBooleanParameter("Active", "A", "Set to true to listen to layer events in the Rhino document.", GH_ParamAccess.item, false); pManager.AddTextParameter("Exclusions", "E", "Provide a list of exclusions to stop reading specific events (Added, Deleted, Moved, Renamed, Locked, Visibility, Color, Active).", GH_ParamAccess.list); pManager[1].Optional = true; }
/// <summary> /// Registers all the output parameters for this component. /// </summary> protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { pManager.AddBooleanParameter("Initialized", "I", "Whether the listener changed from passive to active.", GH_ParamAccess.item); pManager.AddTextParameter("Document Name", "doc", "Name of the Rhino document that is changing.", GH_ParamAccess.item); pManager.AddTextParameter("Layer Path", "path", "Path of the modifed layer.", GH_ParamAccess.item); pManager.AddIntegerParameter("Layer Index", "ID", "Index of the modified layer.", GH_ParamAccess.item); pManager.AddIntegerParameter("Sort Index", "SID", "Sort index of the modified layer.", GH_ParamAccess.item); pManager.AddTextParameter("Event Type", "T", "Type of the modification.", GH_ParamAccess.item); pManager.AddBooleanParameter("Added", "A", "If the layer has been added.", GH_ParamAccess.item); pManager.AddBooleanParameter("Deleted", "D", "If the layer has been deleted.", GH_ParamAccess.item); pManager.AddBooleanParameter("Moved", "M", "If the layer has been moved.", GH_ParamAccess.item); pManager.AddBooleanParameter("Renamed", "R", "If the layer has been renamed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Locked", "L", "If the layer locked setting has changed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Visibility", "V", "If the layer's visibility has changed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Color", "C", "If the layer's color has changed.", GH_ParamAccess.item); pManager.AddBooleanParameter("Active", "Act", "If the active layer has changed.", GH_ParamAccess.item); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { bool active = false; List<string> exclusions = new List<string>();
DA.GetData(0, ref active); DA.GetDataList(1, exclusions);
RhinoDoc thisDoc = null;
bool initialize = false;
string dName = null; string activePath = null; int layerIndex = -1; int sortIndex = -1; string eventType = null; bool added = false; bool deleted = false; bool moved = false; bool renamed = false; bool locked = false; bool visibility = false; bool color = false; bool current = false;
if (active) { thisDoc = RhinoDoc.ActiveDoc;
initialize = (!previouslyActive) ? true : false;
RhinoDoc.LayerTableEvent -= RhinoDoc_LayerTableEvent; RhinoDoc.LayerTableEvent += RhinoDoc_LayerTableEvent; previouslyActive = true;
} else {
RhinoDoc.LayerTableEvent -= RhinoDoc_LayerTableEvent; previouslyActive = false; }
if (ev != null) { dName = ev.Document.Name; layerIndex = ev.LayerIndex; eventType = ev.EventType.ToString();
if (!exclusions.Contains("Active")) { if (ev.EventType.ToString() == "Current") { // active layer has just been changed current = true; }
}
if (!exclusions.Contains("Moved")) { if (ev.EventType.ToString() == "Sorted") { // active layer has just been changed moved = true; }
}
if (!exclusions.Contains("Added")) { if (ev.EventType.ToString() == "Added") { // layer has just been added activePath = ev.NewState.FullPath; added = true; }
}
if (!exclusions.Contains("Active")) { if (ev.EventType.ToString() == "Deleted") { // layer has just been added
deleted = true; } }
if (ev.EventType.ToString() == "Modified") { // layer has been modified activePath = ev.NewState.FullPath;
//skip sortindex eventType = ev.EventType.ToString();
if (ev.OldState != null && ev.NewState != null) { if (!exclusions.Contains("Locked")) { if (ev.OldState.IsLocked != ev.NewState.IsLocked) locked = true;
} if (!exclusions.Contains("Visibility")) { if (ev.OldState.IsVisible != ev.NewState.IsVisible) visibility = true; }
if (!exclusions.Contains("Moved")) { if (ev.OldState.ParentLayerId != ev.NewState.ParentLayerId) moved = true; }
//if (ev.OldState.SortIndex != ev.NewState.SortIndex) moved = true; if (!exclusions.Contains("Renamed")) { if (ev.OldState.Name != ev.NewState.Name) renamed = true; }
if (!exclusions.Contains("Color")) { if (ev.OldState.Color != ev.NewState.Color) color = true; } }
} }
DA.SetData(0, initialize); DA.SetData(1, dName); DA.SetData(2, activePath); DA.SetData(3, layerIndex); DA.SetData(4, sortIndex); DA.SetData(5, eventType); DA.SetData(6, added); DA.SetData(7, deleted); DA.SetData(8, moved); DA.SetData(9, renamed); DA.SetData(10, locked); DA.SetData(11, visibility); DA.SetData(12, color); DA.SetData(13, current);
}
static bool previouslyActive = false; Rhino.DocObjects.Tables.LayerTableEventArgs ev = null;
void RhinoDoc_LayerTableEvent(object sender, Rhino.DocObjects.Tables.LayerTableEventArgs e) { ev = e;this.ExpireSolution(true); }
And for the layer visibility component:
public LayerTools_SetActiveLayer() : base("Set Active Layer", "SetActiveLayer", "Set the active layer in the Rhino document.", "Squirrel", "Layer Tools") { }
/// <summary> /// Registers all the input parameters for this component. /// </summary> protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) { pManager.AddBooleanParameter("Active", "A", "Set to true to change the active layer in Rhino.", GH_ParamAccess.item, false); pManager.AddTextParameter("Path", "P", "Full path of the layer to be activated.", GH_ParamAccess.item); }
/// <summary> /// Registers all the output parameters for this component. /// </summary> protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { pManager.AddIntegerParameter("Layer ID", "ID", "Index of layer that has been activated.", GH_ParamAccess.item); pManager.AddBooleanParameter("Status", "St", "True when the layer has been activated.", GH_ParamAccess.item); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { bool active = false; string path = "";
if (!DA.GetData(0, ref active)) return; if (!DA.GetData(1, ref path)) return;
int layer_index = -1; bool status = false;
if (path != null) {
Rhino.RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc; Rhino.DocObjects.Tables.LayerTable layertable = doc.Layers;
layer_index = layertable.FindByFullPath(path, true);
if (layer_index > 0) { // if exists RhinoDoc.ActiveDoc.Layers.SetCurrentLayerIndex(layer_index, true); status = true; } }
DA.SetData(0, layer_index); DA.SetData(1, status); }
Now originally I was getting exceptions when changing multiple layers' visibility properties, which would cause the Event Listener to fire and try to read the Visibility property before the memory has been released by the Set Layer Visibility component. That led me to add an "Exceptions" input, that would allow me to disable the reading of Visibility events at the source in the Layer Events listener. That helped me manage about 95% of the crashes I was getting, but I still get strange crashes in other event properties, even when that property shouldn't be affected. For instance, I am getting a crash here on the Name property in the event from the delegate function, even though I am only changing Visibility at any one time:
I have a few ideas but they all seem pretty hacky. One is to try to set a flag that is readable by any component in the plugin -- so that the event listener can see if a "set" component is currently running and abort before causing an exception. The other is creating a delay in the event listener, somthing like 200ms, to allow any set components to finish what they are doing before reading the event. Neither seems super ideal.
Any ideas?
Thanks,
Marc
…
edit 29/04/14 - Here is a new collection of more than 80 example files, organized by category:
KangarooExamples.zip
This zip is the most up to date collection of examples at the moment, and collects t
e represents wind flow more accurately in lower heights. The general formula for the log wind profile is:
U(z) = (u*/k)[ln((z-d)/zo)] + psi(z, zo, L) (1)
where U(z) is the mean horizontal wind speed at heigh z, u* is the friction velocity (velocity scale representative of velocities close to a solid boundary), k is the von karman constant (empirically set at 0.41 for rough and smooth surfaces), d is the displacement height, zo is the specific surface roughness, and psi is a stability term.
Most cases assume neutral stability in the atmosphere to eliminate the psi term (i.e. z/L = 0) If not there are much more complex calculations required between temperature and wind speeds, essentially requiring numerical simulations to calculate the profile. With eliminating the psi term, it is easy to calculate the wind speed at any height z, provided we know the wind speed at reference heigh z1, like so:
U(z)/U(z1) = ln((z-d)-zo)/ln((z1-d)-zo1) -> U(z) = .... (2)
where z is the height we are interested in, zo is the roughness height in our case area, z1 is the reference height and zo1 is the reference roughness of the measurements. These are the measurements in the EPW file. The added information so far compared to the power law is that we also need the roughness level of the EPW data (usually near airports where roughness is very low, like 0.0002).
Another simpler way is to calculate the friction velocity first by:
u*=kU(z)/ln(z/zo), (3)
assuming d=0 and z is the reference height of the measurements. Then we can use this to calculate the wind profile.
While d=0 is an assumption I can understand, I do not really agree with accounting for a similar roughness level between the area of measurements and the case area. This is highliy problem and context specific. Especially in urban environments in my opinion it is almost always wrong.
The displacement height (d) is usually calculated as 2/3 of the average height in the area of interest (sometimes "average" has a qualitative connotation as "characteristic"). Accounting for displacement height does introduce a problem though, the wind profile below d meters is undetermined, since ln(x) is undefined for x<0. In order to solve there is a two-step approach which forms these two equations:
U(z) = (u*/k) x ln(z/zo1) for z < a*d
and
U(z) = (u*/k) x ln((z-d)/zo), for z > a*d
Literature mentions that the choice of zo1 and a (i.e. the boundary of the 2 profiles) is quite arbitrary and not very influential in the results. Usually, zo1 is much lower than zo since lower roughness is expected on a higher height, especially in urban zones.
The way I understand it, I think even implementing the simple formula (1) and then using (2) to calculate the profile is enough. For the inclusion of the displacement zone I imagine additional inputs would be required from the users and it would be their responsibility to conduct some sort of sensitivity analysis on the results. Equation (3) would be ok if no data on roughness level of the EPW measurement is available.
Anyways, that's my 0.02c. Bear with me and the mistakes herein, this isn't my specialty by a long shot and I'm just delving into all of this.
Some references:
Wikipedia ofc.
sts.bwk.tue.nl/drivingrain ( a nice page with a lot of additional references. The two-method was mentioned here).
wind-data.ch/tools/profile.php? (a nice online tool that calculates log-wind profiles) and gives the most commonly reproduced values (in the literature) for zo.
Wilcox, Turbulence Modeling for CFD (this is more related to CFD but it gives some background on the physics of the log-law)
Argain et al. 2008, Estimation of the Friction Velocity in Stably Stratified Boundary Layer Flows Over Hills (an example of the complicated calculations when not assuming a neutral stability in the atmosphere)
American Society of Civil Engineers (1999), Wind Tunnel Studies of Building and Structures (as always very good reference, provides the standard categories for zo values)…
oo culm and the web is mad of bamboo slats connected to the culms on either side of the attachment points. To make things clearer (extracted from the above paper):
The authors of the paper did a numerical beam-model in ANSYS to see if they could replicate their theoretical results, and it is fairly correct (some differences due to the non-linear behavior of the semi-ring joints that they use, they remain of an order of 5-10% difference in maximum deflection).
My problem is that I am not able to obtain the same deflection values that the authors did (11.4 mm for a total service load of 7.063 kN applied punctually on the upper chord where the truss elements meet, or even replicate the load/deflection curve). Using an orthotropic material, with the engineering constants taken from (ResearchGate - A bamboo Beam-Column Connection Capable to Transmit Moment), my model is too flexible and I get a maximum deflection of 24.28 mm. I tried other orthotropic mechanical characterizations from other sources (Kathry & Mishra, 2012, Finite element analysis of bamboo and joints using steel members under various loading conditions for design study and Chand , Shukla & Sharma, 2008, Analysis of Mechanical Behaviour of Bamboo (Dendrocalamus strictus) by Using FEM), to no avail.
Of course, the problem could be with the material properties I inputted but I am trying to contact the research team to see directly with them. In the meantime, I am looking to make sure the model itself is not flawed.
It also seems to me that gravity was not accounted for in the numerical of the paper, but it seemed to much of an oversight to be possible (still, the deflection curve of their paper goes through 0).
There are several points I am not quite sure about: after all I am still fairly new to Karamba3D and may still have some things to learn about the inner mechanics of the plugin.
The very first is: should I put eccentricities of the slat-elements of the truss in the definition of their cross-section (directly with the Cross Section box) or as an offset of the beam element (with the ModifyElem box)? I tried both approaches and they seem to yield similar results (max. deflection change by 0.65mm in my latest model).
Second is: is it good practice to subdivide the beam elements in more than one element (and connecting the pieces rigidly) in order to get better results? I imagine some meshing or subdivision is performed when the analysis is run but there is no way of visualizing it (that I found in any case). Subdividing the chord elements seems to give smoother deformation results (though I did not check stress I have to admit). My issue on this topic is that the subdivision of the slat-elements of the web is problematic. On the screenshot below, where the elements are divided in two, lets take the example of node 18. It seems to me that all elements of the diagonal element (28, 29, 34 & 35) are all rigidly connected to the node 18. 28 & 29 are not connected together, independently from 34 & 35. The added rigidity may not be a bad thing for my model, but it is not correct I think? Is there a way of solving the problem?
Element tags:
Node tags:
And here is my GH file (clean enough hopefully): verification-model-V04.gh
Thank you all in advance for any insight (even on the inner logics of Karamba)!
…
currently within a fake euphoria framework - blame China/UAE) and a potential decision about doing/developing this or doing that … well …anyway … read and enjoy.
AEC matters: The good, the bad and the ugly.
The bad news: Rhino is NOT suitable for the job (although some use it … but only in the sense that people use Modo for the so called “hard modeling”). By job I mean things up to shop drawing level + specs + you and me (we call it Final level) – nothing to do with sketches and outlines of some abstract “schematic” topology.
The ugly news: The so called Design-Construct approach gains exponentially momentum especially in countries the likes of China/UAE/BRICS (95% of the whole AEC activity worldwide happens there). DeCo means: AEC engineers deliver some kind of study in a preliminary level and the main contractor splits (outsourcers) the job and assigns the study completion AND the construction to various sup-constructors. That thing appeared first – in a large scale - in Dubai 15 years ago. This means that the era of Sergio Pininfarina is over and out: welcome anonymous Toyota designer. In plain English: days of construction corporations fast replacing practices. Dead men walking.
The good news: All AEC related apps (Revit, AECOsim, Allplan and the likes) are in a lethargic state as regards the brave new world (based on the archaic level driven organization schemas etc etc). Of course they all claim the exact opposite and point that support BIM (nobody mention PLM) better than the other guy. But the 21st century – helped by 2 forthcoming unavoidable crisis (a) about shortage of water (b) about transition from carbon to hydrogen economy – isn’t about bureaucracy: think cost/resources optimization and “fitness” rather than China/UAE type of liquid trend. Days of euphoria fast approaching the Wall.
Top to bottom and visa versa.
Old days Titans (Oscar, Mies, Walter, Pierre Luigi, Frank, Eero, blah blah) outlined things (mostly using crayons) and the rest were struggling to translate these in reality in an one way vector like process : Top to bottom that is. These days the inverse gains momentum : when in the whole consider the part … validate … redo … validate … redo. This means bottom to top geared with top-to-bottom. In plain English : child imposes rules to parent and parent imposes rules to child. This means classic MCAD feature/history modeling (CATIA/NX/MS). This is something that Rhino can’t do (not to mention that Rhino is a surface modeler – a rather critical fact).
The parts that are bigger than the whole.
Go there ( http://www.behance.net/gallery/2885057/a-myriad-of-cables) are inspect the whole thing: it’s a parametric nightmare made with the other guy (Generative Components – slower than a Skoda + bugs + why bother?). But the whole (masts and membranes and the likes) means nothing here: focus to the details that are critical for connecting this with that. Complex feature driven solids that are made with internal (on a per se basis) parameters (like fillets required for casting or radius for cable anchoring) whilst they comply with external rules/parameters (cable angles, topology clash issues etc etc). So the whole outlines possibilities … and the part either can follow…or the part must change…or the whole must change. Can you do that with GH/Rhino? And if not what’s missing? (lot’s of things to be honest).
Some other "similar" things:
The narrow picture.
I agree with what others already said and with pretty much all Ola’s points – especially the visual drag-and-drop path mapper (i.e. a visual data manipulator so to speak) and the enable/disable components in groups capability.
Some other suggestions:
A multi canvas capability. As things are right now…it’s like working in Rhino in one view (rather unsuitable I guess). In fact …since overlapping views they don’t work in Rhino…well…you know, he he.
A working auto profile arrangement capability (non twisted Loft/Sweep and the likes). Worth 1Bn dollars that one.
Ability to locate components that caused this or that in the Rhino view: meaning a 2 way communication approach : GH makes things happen in Rhino and things can indicate their cause in the GH canvas.
A robust collection of components that bake stuff in nested blocks (emulating some primitive assembly/component way of thinking). Why may you ask? Well … the whole objective is to talk to CATIA (via STEP) don’t you agree? CATIA makes things happen in real-life not Rhino.
A robust collection of components that can create real-life parametric tensile membrane solutions (get some inspiration from FormFinder: useless because it’s academic but good to point the way). Membranes (and geodesics) are the future.
I could continue at infinitum but IMHO the big picture is worth 12345,67 “focused” GH improvements.
May the Force (the dark option) be with us all.
…
Introduction to Grasshopper Videos by David Rutten.
Wondering how to get started with Grasshopper? Look no further. Spend an some time with the creator of Grasshopper, David Rutten, to learn the
into curves, and so I would like to use within Grasshopper.
I would really appreciate if anyone well versed in RhinoScript/VB.Net Syntax would be kind enough to help out.
Thank you for reading this.
' ConvertTextToGeometry.rvb -- September 2008
' If this code works, it was written by Dale Fugier.
' If not, I don't know who wrote it. ' Works with Rhino 4.0.
Option Explicit
Sub ConvertTextToGeometry
' Declare local variables
Dim obj_list, obj, saved_plane, cmd
Dim font, height, plane, style, text, bold, italic
' Select annotation objects
obj_list = Rhino.GetObjects("Select text to convert to geometry", 512, True, True)
If Not IsArray(obj_list) Then Exit Sub
' For speed, turn of screen redrawing
Call Rhino.EnableRedraw(False)
' Save the current construction plane
saved_plane = Rhino.ViewCPlane()
' Process each selected object
For Each obj In obj_list
' Weed out just the text objects
If Rhino.IsText(obj) Then
' Acquire the text parameters
font = "<single_stroke_font_name>"
height = Rhino.TextObjectHeight(obj)
plane = Rhino.TextObjectPlane(obj)
style = Rhino.TextObjectStyle(obj)
text = Rhino.TextObjectText(obj)
If (style And 1) Then
bold = "_Yes"
Else
bold = "_No"
End If
If (style And 2) Then
italic = "_Yes"
Else
italic = "_No"
End If
' Set the current construction plane
Call Rhino.ViewCPlane(, plane)
' Add a new text object (geometry)
cmd = "_-TextObject "
cmd = cmd & "_GroupOutput=_Yes "
cmd = cmd & "_FontName=" & font & " "
cmd = cmd & "_Italic=" & italic & " "
cmd = cmd & "_Bold=" & bold & " "
cmd = cmd & "_Height=" & CStr(height) & " "
cmd = cmd & "_Output=_Curves "
cmd = cmd & "_AllowOpenCurves=_Yes "
cmd = cmd & Chr(34) & text & Chr(34) & " "
cmd = cmd & "0"
Call Rhino.Command(cmd, 0)
' Delete the original object
Call Rhino.DeleteObject(obj)
End If
Next
' Restore the saved construction plane
Call Rhino.ViewCPlane(, saved_plane)
' Enable screen redrawing
Call Rhino.EnableRedraw(True)
End Sub
…