Stream Object IDs

Hello everyone!

I would need only the IDs of those objects that appear in the speckle viewer from a stream.
I tried to do this using GraphQL and managed to retrieve all the objects, but I don’t know how to modify it to get the desired result.

Thank you in advance for your answers!

image

1 Like

I’m unclear; what is your desired result? If it is just ids then you could not include data in your query.

What are you hoping to achieve, perhaps we can help make that clearer.

For example, I have these 3 objects, each of them has an ID, but when I fetch the objects, it retrieves not only these 3, but a total of 12. I would like only the IDs of these 3 objects to be fetched.

Where was the data originating?

A Speckle Commit can have other objects detached from the source geometry that enables the Speckle Magic to work.

Or the objects could be views. or data chunks defining the meshes

If you want to filter to just those visible, you can use query filter.

firstly, you can limit the recursion through all the children of children you see, e.g.

 children(depth:1)
{
  "data": {
    "stream": {
      "object": {
        "children": {
          "objects": []
        }
      }
    }
  }
}
 children(depth:2)
{
  "data": {
    "stream": {
      "object": {
        "children": {
          "objects": [
            {
              "id": "4c66c1437fc429f23f919faacb29ddbe",
              "data": {
                "id": "4c66c1437fc429f23f919faacb29ddbe",
                "name": "Default",
                "visible": true,
                "elements": [
                  {
                    "referencedId": "80de87ca1e03b571bac2526968a98515",
                    "speckle_type": "reference"
                  },
                  {
                    "referencedId": "e4f90023ad3b18dd42e71c9030d21ffe",
                    "speckle_type": "reference"
                  },
                  {
                    "referencedId": "be753a5b55038387e80a4da76b2ea03c",
                    "speckle_type": "reference"
                  }
                ],
                "speckle_type": "Objects.Organization.Collection",
                "applicationId": "03f65291-4e2b-421a-832d-bb698dabfbd9",
                "collectionType": "layer",
                "totalChildrenCount": 0
              }
            }
          ]
        }
      }
    }
  }
}

Increasing that value will return more objects - again; it depends on where the data originates as to what the structure of the commit ends up being

If you want only to have display geometry objects, you can try.

children(depth:1000, query: $myQuery)

with query variables:

{"myQuery":[ 
  	{
      "field": "displayValue",
      "value": "_",
      "operator": "!="
    }
]}

In my example stream this gives:

{
  "data": {
    "stream": {
      "object": {
        "children": {
          "objects": [
            {
              "id": "3357d9d5d1f88a4809bb13d5eabdebf4"
            },
            {
              "id": "9234f155724b785653a53c9fb7b2d429"
            },
            {
              "id": "da637f6e105f119be52e5a87a6e7afc4"
            },
            {
              "id": "e19955cd2e295619587b53a748f7c246"
            }
          ]
        }
      }
    }
  }
}

This might work for you, except that in my case, those 4 geometry objects are actually visible in the viewer as 3 instances of a Block, so instead, your result could be a single object inside the definition object and not the three instances.

What you want with “the ids of the visible objects” may not be so straightforward a question; hence my question to you of, can you describe your intent, and we can guide you toward a solution?

1 Like

The current model data will come from Blender initially and later from Revit. By storing the IDs of the models, I can ensure that the viewer displays the elements of the model with different colors according to our requirements.
I need to generate statistics on this (how many elements are in each color and how many are not colored). I store the IDs of the already configured elements, but I would also need to know the total number of displayed elements (the ones that can be clicked on in the viewer).
I would need the IDs of these elements.

For example, here it shows that there are 29 elements in dark green, 20 in yellow, and so on. I would need the IDs of the elements that are not colored.

This is also necessary in order to avoid retrieving unnecessary data during the request. In the above model, for example, there are approximately 900 clickable elements, yet it retrieves 24,000 elements, which significantly increases the runtime.

And one more thing, is it possible to set the limit value to retrieve not only 100 items, but dynamically retrieve all of them?

1 Like

Thanks for a bit more detail.

We wanted to get even more insight and see a bigger picture. But sometimes, the objective context is helpful before we drill down to a solution.

Please correct my summary if I am incorrect.

  • You are building an app and using the Speckle Viewer package
  • You want to colour certain objects according to some logic post-read
  • You want to perform a count on displayed objects by colour or no colour
  • you will display those counts with an overlay “widget.”

Are we closer to understanding the bigger picture?

As you have seen, the retrieved data via GraphQL is pretty raw and nested. It includes everything that has an ID which is, in turn, everything that is “detached” and stored as a unique row in the :speckle:Speckle database, This includes chunks of data like lists of vertices, level definitions, colour definitions, cameras etc.,

There is obviously a data criterion that determines what colours you want to apply, you could filter by that instead, or what you might want to do, considering you already are using the Viewer, is to reference that as a data source instead of making a separate query and wrangling that.

Before I make more assumptions am I close so far?

Approximately yes.
I store the IDs of the elements displayed and already set in the viewer in an SQL database (in the format of streamId - objectId - color). I retrieve them from there and apply colors to them on the frontend.
For example, if I retrieve the stream objects consisting of 3 cubes, I get the following 12 elements.

image

However, only these 3 are actually clickable elements.

image

And I only need these 3, as well as the same for other streams.

Hi @Gircsi117

If we consider that clickable objects are the objects with any kind of visual representation, then I can suggest an approach on finding out the ids of clickable objects via the viewer directly. Please bear in mind that the following code is part of an area of the viewer API which we haven’t properly formalized yet, that’s why it’s not yet properly documented.

    const root = viewer.getWorldTree().findId('ROOT')
    const nodes = viewer
      .getWorldTree()
      .getRenderTree()
      .getRenderViewNodesForNode(root, root)
    const clickableIds = nodes.map((node: TreeNode) => node.model.raw.id)

This will provide you with the ids of the objects from the speckle stream which have a visual representation of any kind, which you can then feed into the filtering API any way you like.
There is a note though. Nodes inside block instances will have their node.model.raw.id set their own id, concatenated with their block’s id (or multiple block ids if there is a deeper nested hierarchy). They will still work fine with the filtering API however.

I’m assuming you need specific colors for each group of objects, so you are using setUserObjectColors with you own colors and id sets. If specific colors are not needed you could simply filter the objects based on properties you define and set during authoring of the model.

Cheers

2 Likes

How can I achieve the same result using spekcklepy?