ours looks like). Anyway, you'll probably want to start with a Fader 1-way. I set mine up to go from 0 to 300 over the course of 6 seconds. Then I just wrote a very quick C# component to check the output of the Fader component and whether it met one of three conditions. Here's the code (very simple). Note: you'll need to use the input manager to remove one of the Y input and the output manager to add 2 more outputs (B & C).
if (x <= 100) { A = true; B = false; C = false; } if (x > 100 && x <= 200) { A = false; B = true; C = false; } if (x > 200) { A = false; B = false; C = true; }
Now, we know if at any given Fader value if it's in the first phase, second phase, or third phase. I output a boolean value which can also be considered a 0 or 1 if converted to an integer. So, if I multiply those boolean values by 255, then the one that is true will be 255, and the others will always be 0. Now, you should have your color scheme which switches depending on what phase its in. Simply connect that to the Uno Write component (with the Firefly Firmata sketch loaded on your board) and send the color values to the board as PWM values.
Some things I should note... You probably notice the Fader component looks a little different (it's missing the start input and I'm using the GH_Timer). I've decided (for good reason) to abandon the Form Timer I was using in a lot of the Firefly components in favor of the newly re-written GH_Timer component. So, in order to get the Fader component to update in the next version, you have to connect a Timer and turn it on (not that much different). But, it's significantly faster. Part of the reason is that the form timer just wasn't fast enough to get really smooth results... Now, it's blazing fast. I've incorporated this Timer scheme in a lot of the Firefly components and the results are roughly 10x faster. Since, you're only switching values (and not trying to quickly modulate the PWM values) the current version of Firefly should be just fine (just use the Start input to start the Fader component). But, when we release the next version (hopefully very soon), this may change a bit. Anyway, I hope that clarifies it a bit. I've attached a screenshot below. I didn't include the file because I've got a newer version of Firefly that would just crash on you (or not open properly)... but hopefully you can get how to do it.
…
of a hack to push it to an android device, and you can't use labels, which is a very bad point!
...
I won't buy an Iphone!
The other is Control OSC. It looks rougher, but it has a lot of advantages to me.
+ Game of Life included!
+ you can use and update labels :))
+ Has a nice muti touch widget unfeatured in touch osc
+ You can script the interface using java script manipulation in gh, stream it to your dropbox and update in one "tap", as follows
Does anyone have experience with scripting interfaces for this software? I'm stuck already. I know nothing of java script to begin with. As you can see I managed to format the labels but the osc message I could not find a way, it stays untouched.
Just in case someone knows better, here are my "objects" (I said that right?). The userXXX are replaced in GH.
{ "name":"userName", "type":"Slider", "x":(xPadding + .11), "y": yPadding, "width":.82, "height":.082, "color":"userColor", "min":userMin, "max":userMax, "ontouchmove" : "var roundedvalue = this.value.toFixed(userFix); LbluserName2.changeValue(roundedvalue)", "onvaluechange": "oscManager.sendOSC('/userName', 'f', this.value.toFixed(userFix))",},{ "name":"LbluserName1", "type":"Label", "x":xPadding, "y": yPadding, "width":.1, "height":.05, "color":"userColor", "value": "userName"},{ "name":"LbluserName2", "type":"Label", "x":xPadding, "y": (yPadding + 0.05), "width":.1, "height":.05, "address":"/userName", "color":"userColor", "value": 0},…
ices" which i found very intresting , I have your thesis and it will be the base of my futur work, I'm a graduate student in bioclimatic architecture and environment in Constantine -Algeria , I will prepare a thesis for my master degree in the theme of " parametric design, the dynamic envelope and intelligent façade" and really I need your help, if you can send me your work in grasshopper in(.ghx) mentioned in the "APPENDIX D SOLAR CONTROL VISUAL DEFINITION "(GRASSHOPPER),because i can't download it from the web site , I'm juste a beginner in grasshopper so I want to master the link between all the elements ,for this reason I would like to master your exemple in grasshopper as beginning , and I'll work with daylighting + thermal comfort in my thesis which is the continuity of your work, can you share your exemple with me please ? and why did you choose a 200 btu/ft² as a limits for direct normal irradiance , what is the formula ? I'm waiting for your response because it's so importante for my work , and i promise you , i will put your name in my references . thank you karla. the files needed are: the part which contains: 1-Solar Irradiance / TMY3 Excel Data (in grasshopper) 2-:Surface Geometry Analysis / Grid Pattern Selection (in grasshopper) 3-: Solar Profile Angles (in grasshopper)
4- Shading Geometry Profile Angles (in grasshopper) …
dMAC.gh license requesting utility now allows you to generate an automatic email embedding your data.
Robot Library:• New IRB4400(60) robot preset.• New IRB6400Rex(200) robot preset.• New IRB6620(150) robot preset.• New IRBT6004 track preset. • New Track Creator component.
Base Pack:• The Inverse Kinematics Solver now handles inputs for track positioners (linear external axis).• The Inverse Kinematics Solver now handles flip overrides to access alternative configurations of the elbow, of the wrist, or both.• New control in the right-click menu of the Inverse Kinematics Solver allowing to change the threshold for large reorientation analysis.• The Rapid Generator was outputing wrong confdata for axis with a rotation between +270 and +360°, this is solved.• The Rapid Generator was outputing wrong local rotation values for targets when a Work Object was used under certain conditions, this is solved.• The Rapid Generator is now outputing the declaration of the Work Object when it is different than WObj0.• New controls in the right-click menu of the RAPID Generator allowing to set custom precisions for coordinates and rotation values to be used in the code, in order to optimize the size of the program. • New control in the right-click menu of the RAPID Generator allowing to force the formating of the output for multi-robot setups.• New Track Position Solver component.• New External Axis Manager component.• New Signals Manager component.• New Flip Value List component.
Communication Pack:• The HAL To Controller component now allows to manage Digital Outputs (DO) and simulated Digital Inputs (DI) signals in real-time.• The OSC To HAL component is now compatible with remote digital signal management. • The OSC To HAL component is now automatically detecting the device (iPhone or iPad) you are using.• The TouchOSC layout has a new Digital I/Os management menu (2*15 channels on the iPad, 2*6 channels on the iPhone).…
three categories, each one corresponding to different shapeType_ input:- polygons (shapeType_ = 0): anything consisted of closed polygons: buildings, grass areas, forests, lakes, etc
- polylines (shapeType_ = 1): non closed polylines as: streets, roads, highways, rivers, canals, train tracks ...- points (shapeType_ = 2): any point features, like: Trees, building entrances, benches, junctions between roads... Store locations: restaurants, bars, pharmacies, post offices...
So basically when you ran the "OSM shapes" component with the shapeType_ = 2, you will get a lot of points. If you would like to get only 3d trees, you run the "OSM 3D" component and it will create 3d trees from only those points which are in fact trees. You can also check which points are trees by looking at the exact location on openstreetmap.org. For example:
Or use the "OSM Search" component which will identify all trees among the points, regardless of whether 3d trees can be created or not.However, when it comes to 3d trees there is a catch:
Sometimes the geometry which Gismo streams from OpenStreetMap.org does not contain a "height" key. Or it does contain it but the value for that key is missing.OpenStreetMap is free editable map database, so anyone with internet access and free registered account on openstreetmap.org can add features (like trees) to the map database. However, regular people sometimes do not have height measuring devices which are needed for specific objects as trees.So "OSM 3D" component will generate 3d trees from only those tree points which contain a valid "height" key.However, a small workaround is to input a domain(range) into the randomHeightRange_ input of "OSM 3D" component (for example the following one: "5 to 10"):
This will result in creation of other 3d trees which do not have defined height, by randomizing their height. randomHeightRange_ input can also be applied to 3d buildings, and it is definitively something I need to write a separate article on.
In the end it may be that nobody mapped the trees in the area you are looking for.
After you map a tree to openstreetmap.org then it will instantly be available to you or any other user of Gismo. I will be adding some tutorials in the future on how this can be done. But probably not in the next couple of weeks.
Let me know if any of this helps, or if I completely misunderstood your issue.…
Added by djordje to Gismo at 3:52am on February 8, 2017
long as the component runs, the list gets generated (screenshot below). It's based on a process explained by James Ramsden here.
However, the list is only generated after all inputs are defined, so for components that have certain inputs without default values, the user has to set these inputs before the list gets generated. Is there any way to force the component to generate the list even before the component has been given all input values? Here is sample code for the issue; the list is only generated after input1 has been defined:
using System; using System.Collections.Generic; using Grasshopper.Kernel; using Rhino.Geometry; using System.Drawing; namespace IntraLattice { public class MyComponent1 : GH_Component { GH_Document GrasshopperDocument; IGH_Component Component; public MyComponent1() : base("MyComponent1", "Nickname", "Description", "Category", "Subcategory") { } protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) { pManager.AddLineParameter("Input1", "Input1", "An input", GH_ParamAccess.list); pManager.AddIntegerParameter("Input2", "Input2", "The list selection input", GH_ParamAccess.item, 0); } protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) { pManager.AddLineParameter("Output", "Output", "Dummy output", GH_ParamAccess.item); } protected override void SolveInstance(IGH_DataAccess DA) { // 0. Generate input menu list Component = this; GrasshopperDocument = this.OnPingDocument(); if (Component.Params.Input[1].SourceCount == 0) TopoSelect(ref Component, ref GrasshopperDocument, 1, 11); // 1. Retrieve/validate input var input1 = new List<Line>(); int input2 = 0; if (!DA.GetDataList(0, input1)) { return; } if (!DA.GetData(1, ref input2)) { return; } var nodes = new List<Point3d>(); var lines = new List<Line>(); // Some dummy code, that will set the output depending on the value selection list // create first point Point3d pt1 = new Point3d(0, 0, 0); Point3d pt2; // set output depending on value list selection if (input2 == 0) pt2 = new Point3d(5, 0, 0); else pt2 = new Point3d(0, 5, 0); // create pt2 Line line = new Line(pt1, pt2); DA.SetData(0, line); } /// The 'index' input represents the input index (first input is index 0) /// The 'offset' parameter is the vertical offset of the menu, to help with positioning /// </summary> public static void TopoSelect(ref IGH_Component Component, ref GH_Document GrasshopperDocument, int index, float offset) { //instantiate new value list var vallist = new Grasshopper.Kernel.Special.GH_ValueList(); vallist.ListMode = Grasshopper.Kernel.Special.GH_ValueListMode.Cycle; vallist.CreateAttributes(); //customise value list position float xCoord = (float)Component.Attributes.Pivot.X - 200; float yCoord = (float)Component.Attributes.Pivot.Y + index * 40 - offset; PointF cornerPt = new PointF(xCoord, yCoord); vallist.Attributes.Pivot = cornerPt; //populate value list with our own data vallist.ListItems.Clear(); var items = new List<Grasshopper.Kernel.Special.GH_ValueListItem>(); items.Add(new Grasshopper.Kernel.Special.GH_ValueListItem("Choice 0", "0")); items.Add(new Grasshopper.Kernel.Special.GH_ValueListItem("Choice 1", "1")); vallist.ListItems.AddRange(items); // Until now, the slider is a hypothetical object. // This command makes it 'real' and adds it to the canvas. GrasshopperDocument.AddObject(vallist, false); //Connect the new slider to this component Component.Params.Input[index].AddSource(vallist); Component.Params.Input[index].CollectData(); } protected override System.Drawing.Bitmap Icon { get { return null; } } public override Guid ComponentGuid { get { return new Guid("{ebc17377-4900-4e14-b33e-0b1c66ef2ade}"); } } } }
Thanks in advance…
both my plotter/cutter and wide format printer. I had been running the plotter from my main work laptop - a Win10 machine via the plotters USB port. As it turns out you can't get Win XP drivers for this USB connection so I needed another solution.
I tried to use the plotters DB25 serial port connection using an old DB9 to DB25 modem cable I had in my collection = no luck the plotter wouldn't talk. A bit more research and it turns out these plotters need a 'null modem' cross over cable to operate. I found a pic of the correct wiring online and made up my own with some cable and connectors from the local electronics hobby shop.
With this hooked up and using Hyperterminal I was able to fire some codes to the plotter directly and get a response back - winning!
At this point I got my original code working with the 'net use' redirect from LPT1 to COM1.
HOWEVER - being that the plotter was now on a COM port there are a few more interesting things you can do with it - one is being able to read the paper size/cut area from the printer.
So what I needed to to was find a way to send and receive data to/from the plotter using the serial port.
A bit of research into .NET's serial port interface and using a bunch of small pieces of test code I have manged to completely re-jig this driver.
Upgrades include:
- Direct Serial Port comms using Null Modem cable (a USB to serial adaptor + null modem should also work)
- Plot area read from the plotter - a rectangle the size of the plot area is placed on a separate layer and coloured red
- Testing to see if selected plotting curves are both closed and inside of the cutting area - with errors shown and exiting if they are not right.
- After plot 'parking' of the plot head at the end of the cut items + an adjustable offset (currently requires manual resetting of origin on the plotter before for next cut)
Great thing is it is now 100% running within Rhino Python - no DOS command line calls = no flashing up of the CMD wind. Also no temp files needed on the HDD and no limit to number of curves that can be plotted - tested with 200 or so with no issues.
Overall very happy with whole project - have learnt a LOT about Python and .NET interfacing AND ended up with a very handy/useful tool.
Cheers
DK
# This code is a WIP # It plots directly to a DGI Plotter# via the serial port
import System.IO.Ports as Portsimport rhinoscriptsyntax as rsimport time
#Some setup valuescom_port = 'COM1' #change to match plotter port baud_rate = 9600 #change to match plotter settingplotter_step = .025 #mmfinsh_offset = 10 #mm
#Delete old cutting area and cut objectsif rs.IsLayer('Cutting Area'): rs.PurgeLayer('Cutting Area')if rs.IsLayer('Cutting Objects'): rs.PurgeLayer('Cut Objects')
#Setup Serial PortMyport = Ports.SerialPort(com_port)Port_Write = Ports.SerialPort.WriteMyport.BaudRate = baud_rateMyport.ReadTimeout=5000 #5 secsMyport.Close()Myport.Open()
#Setup PlotterPort_Write(Myport, 'PU;PA0,0;IN;\n')Port_Write(Myport, 'SP1;\n')Port_Write(Myport, 'PA;\n')time.sleep(2)
#Read the Paper size from PlotterPort_Write(Myport, 'OH;') #HPGL read limits codetime.sleep(2)
return1 = ''papersize = ''count = 0char_in_buffer = 0chars_in_buffer = Ports.SerialPort.BytesToRead.GetValue(Myport)
if chars_in_buffer == 0: print 'Plotter not ready' Myport.Close() exit()
while (count < chars_in_buffer): return1 = Myport.ReadChar() papersize = papersize + chr(return1) count = count + 1
papersize = papersize.split(",")rect1 = (float(papersize[2])*plotter_step)rect2 = (float(papersize[3])*plotter_step)
print 'Cutting area = ' + str(rect1) + 'x' + str(rect2)
#place cutting area curve on its own layer, make it red and lock itplane = rs.WorldXYPlane()cutting_area = rs.AddRectangle( plane, (rect1), (rect2))rs.AddLayer (name='Cutting Area', color=(255,0,0), visible=True, locked=True, parent=None)rs.ObjectLayer(cutting_area, 'Cutting Area')
#get plotting objects
allCurves = rs.GetObjects("Select curves to plot", rs.filter.curve)
#test to see if these are closed curves - exit if not
for curve in allCurves: test_closed = rs.IsCurveClosed(curve) if test_closed == 0: print "One or move of these curves are not closed" Myport.Close() exit()
#test to see if these are inside cutting area - exit if not
for curve in allCurves: test_inside = rs.PlanarClosedCurveContainment(curve, cutting_area)
if test_inside==0 or test_inside==1: print "One or more of these curves are outside of cut area" Myport.Close() exit()
#All ok - convert to points and send data to printer
rs.AddLayer (name='Cut Objects', color=(0,255,0), visible=False, locked=True, parent=None)
for curve in allCurves: Port_Write(Myport, 'PU;PA;SP1;\n') polyline = rs.ConvertCurveToPolyline(curve,angle_tolerance=5.0, tolerance=0.025, delete_input=False, min_edge_length=0, max_edge_length=0) points = rs.CurveEditPoints(polyline) rs.ObjectLayer(polyline, 'Cut Objects')
# PU to the first point x = points[0][0] y = points[0][1] Port_Write(Myport, 'PU' + str(int(x / plotter_step)) + ',' + str(int(y / plotter_step)) + ';\n') # PD to every subsequent point i = 1 while i < len(points): x = points[i][0] y = points[i][1] Port_Write(Myport, 'PD' + str(int(x / plotter_step)) + ',' + str(int(y / plotter_step)) + ';\n') i += 1
Port_Write(Myport,'PU;\n')
#find the far end of the cutbox = rs.BoundingBox(allCurves)far_end = str(box[1])far_end = far_end.split(",")far_end = far_end[0]far_end = float(far_end)/plotter_stepfar_end = (int(far_end))+ finsh_offsetfar_end = str(far_end)print (far_end)
#return plotter home and close portPort_Write(Myport, 'PU;PA' + far_end + ',0;IN;\n')Port_Write(Myport, 'SP1;\n')Port_Write(Myport, 'PA;\n')Myport.Close()time.sleep(10)…
point and tangent of this new curve to generate the direction for the next curve.
The problem I am running into is that sometimes the curve loops back on itself past the designated endpoint. The loop is so tight that you can't tell that it is actually looped and it just looks like the curve extends past its endpoint. Other times Interpolate Curve generates the arc opposite the desired one. Since I am generating a tangent to this curve at the end point it can obviously cause problems for the direction of the next curve.
I have been taking care of the problem by changing the number of points used in the curve, but am finding that even high numbers of points will generate errors and it is seriously undermining my confidence in the solution. Attached are images of the outputs with the only variable changing is the number of points used to construct the curves.
Any recommendations or insights are welcome.
30 Points (good output)
62 Points (seriously no bueno)
63 Points (um, no thanks)
199 Points (good output)
200 Points (wth?)
…
freeform Mesh Solid???? Because, that's how it really goes in the Nature!
my Try:
step 1) build the facade skeleton with the outlines intersected from Voronoi cells and the skin of skyscraper. then use a some borrowed GH-sets to loft those outlines.
step 2) use some other borrowed GH-sets to loft the whole 3D Voronoi Skeleton. Then bake them. and then use "mesh boolean" in Rhino, to get the inner 3D Skeleton for the Skyscraper.
step 3) combine them, it's not perfect, but not too bad.
This is the result.
Problem: When I try to make the Point cloud more denser, the "mesh boolean" allways failed out. Because those Skeleton-meshs are too komplicated to split.
any ideas??
Thanks!!!
…