[Solved] Component coordinates on GH canvas

How can I get the location of a component on GH canvas?

Can I do that?

1 Like


Thanks for the reply Nathan,

I’m so lost in this API :frowning:

How can I make my component “self-aware” of it’s own location on the canvas.

Do I need to be in SDK mode and override GH_Attributes?

If you have a pointer to any instance of a class which implements IGH_DocumentObject, then you can get its IGH_Attributes and the attributes have both a Pivot (location) and Bounds (outer bounds) property. The pivot is not required to be inside the bounds, so @nathanletwory’s suggestion to just look at the bounds is good.

Any object which is part of a Grasshopper document (and can thus be on the canvas) must implement IGH_DocumentObject. This category covers everything, from components to sliders, to groups, to jumps, to scribbles, … everything. If an object also wants to participate in solutions, then it must implement the IGH_ActiveObject interface, which just extends IGH_DocumentObject with a bunch of additional methods. Scribbles and groups for example don’t do anything inside solutions, so they do not bother with IGH_ActiveObject.

The attributes of any object is a type which does all the UI stuff.* It knows how to draw the object on the canvas, whether or not a mouseclick was on or off the object, whether a specific location would trigger a tooltip or menu for the object. It also handles selection logic, which can be pretty complicated for objects such as sketches or scribbles.

* Except for populating the object menu, that is done by the object itself.



Thanks @nathanletwory ,

Now that is helpful.

I spent last evening-night trying different “Attributes” attributes for numerous classes from the api, and I could not get proper result. Either “Bounds” were missing, or I simply didn’t get a result.

Just started experimenting what I can do with this “ghenv” secret variable, this morning.

Could you explain what ghenv is calling?
I assumed it’s Grasshopper.Environment, but I don’t see that in the dropdown.


See Giulio’s reply here:

Thanks for the reply @AndersDeleuran,

:smiley: so None:

Sorry, there is no more documentation than what you can see with autocompletion. However, there is also nothing else there, other than that! You can see its sourcecode here:
The most important information, as you already discovered, is Component, which returns a GH_Component instance (a ZuiPythonComponent instance, to be precise – but this might change in the future). GH_Component is defined in the Grasshopper SDK.

I have the feeling this (ghenv) is very useful thing but with Documentation little to none…:thinking: :man_facepalming:

1 Like

Hi David, for some reason I can get this to work on components but not a panel.

How can I get the center of a panel?


from System.Drawing import PointF
a = ghenv.Component.Params.Input[0].Sources[0].Attributes.Bounds
b = PointF(a.X + a.Width / 2, a.Y + a.Height / 2)


private void RunScript(object x, ref object A, ref object B)
  var bounds = Component.Params.Input[0].Sources[0].Attributes.Bounds;
  A = bounds;
  B = new PointF(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2);

PanelCenter.gh (5.0 KB)


Thanks Mahdiyar,

My code used Point, so I was hoping that changing to PointF would make it work, but it’s not.

my sourceComponent is the target panel…

                if (sourceComponent != null)
                    //PointF sourceCenter = new PointF();

                    RectangleF bounds = sourceComponent.Attributes.Bounds;
                    PointF sourceCenter = new PointF(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2);

                        new Pen(Color.Black, 2f) { DashCap = DashCap.Round, DashPattern = new[] { 1f, 0.25f } },

This gives me a wire between my component and a target component, but the wire does not work if the target is a panel.

DefaultPanel_VS.zip (3.7 MB)

You need to replace these two lines:

IGH_Component targetComponent = Owner.OnPingDocument().FindComponent(Owner.targetPanelComponentGuid);
IGH_Component sourceComponent = Owner.OnPingDocument().FindComponent(Owner.sourcePanelComponentGuid);

to something like this:

var targetObject = Owner.OnPingDocument().FindObject(Owner.targetPanelComponentGuid, true);
var sourceObject = Owner.OnPingDocument().FindObject(Owner.sourcePanelComponentGuid, true);

DefualtPanel.zip (37.4 KB)

1 Like

Beautiful @Mahdiyar, thanks very much. I guess the Panel isnt a IGH_Component then… Lesson learned.

I’ve shared my project here: https://github.com/Sonderwoods/DefaultPanel