Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metadata inheritance #641

Open
lilleyse opened this issue Mar 1, 2022 · 3 comments
Open

Metadata inheritance #641

lilleyse opened this issue Mar 1, 2022 · 3 comments

Comments

@lilleyse
Copy link
Contributor

lilleyse commented Mar 1, 2022

3D Tiles Next defines different levels of metadata granularity but it doesn't define the relationship or inheritance model of this metadata. There are a lot of ways this could be done.

First, metadata could be inherited based on the tileset structure — a feature would inherit its content's metadata, which would inherit its tile's metadata, which would inherit its tileset's metadata. This is a "BELONGS-TO" rather than "IS-A" relationship. A feature is not a tileset, but it belongs to a tileset and has access to the tileset's metadata.

This is how it's implemented in CesiumJS in getPropertyInherited.

One aspect that needs further discussion is whether a tile should inherit its parent tile's metadata. It seems like right thing to do but the implementation may not be straightforward or performant.

Metadata could also be inherited in a more abstract sense. Batch Table Hierarchy allows a metadata entity to belong to other metadata entities and get access to their properties. In EXT_structural_metadata terms this would be a row in a property table pointing to a row in another property table. This is also a "BELONGS-TO" relationship, but more abstract since it doesn't use the tileset structure. Arguably content groups are similar.

Then there is the "IS-A" relationship which implies class hierarchies. Unlike the previous approaches, the class hierarchy would need to be defined in the class definition. This has some benefits but it isn't as good for composability.

I've left out some details here to keep this brief to start. What metadata inheritance model makes the most sense for 3D Tiles?

@lilleyse
Copy link
Contributor Author

lilleyse commented Mar 1, 2022

Also CC #558. This issue is essentially a superset of that.

@javagl
Copy link
Contributor

javagl commented Mar 2, 2022

One question is on which level this inheritance should be defined or specified.


Right now, the 3D Metadata Specification has no connection to tilesets, or any sort of hierarchically structured data. So any form of inheritance that was supposed to be defined on this level would have to be defined solely on the level of the concepts that are contained in this specification - and this is essentially on the level of Classes and Entities.

In this context, "inheritance" could be understood in different ways. This is not about "inheritance" among the Metadata Classes in an object-oriented sense. It is rather about a way of accessing Metadata from one Entity starting from an Entity on a "finer" granularity level

One could try to think about a way of defining this sort of inheritance on the level of the 3D Metadata Specification. Right now, an Entity is just an instance of a Class. One could consider extending that, so that each entity has a set of "parent entities". But it could be hard to cleanly define these references to Entities without any particular encoding.


It could make more sense to define such an "inheritance" in the 3DTILES_metadata specification. There the encoding is known to be JSON, and information about "inherited" metadata could be located in the metadataEntity.schema.json.

The question about how to encode references to Entities still has to be answered. Referring to the diagram from the first comment, there could be metadata for the tileset, tile, groups, and content. The "inheritance" should then mean that each metadata Entity should be able to "refer" to entities on a coarser granularity level:

// In tileset
{
  "class": "city",
  "properties": { "name": "New York City" ... },
  "globalId" : "ID_TILESET_0"
}

// In tile
{
  "class": "borough",
  "properties": { "name": "Manhattan" ...  },
  
  "globalId" : "ID_TILE_0",
  "parentEntities": [ "ID_TILESET_0" ]
}

// In content group
{ 
  "class": "layer",
  "properties": { "color": "red", ... },
  
  "globalId" : "ID_GROUP_0",
  "parentEntities": [ "ID_TILESET_0" ]
}

// In content
{ 
  "class": "building",
  "properties": { "height": 123 ...  },
  
  "globalId" : "ID_CONTENT_0",
  "parentEntities": [ "ID_TILE_0", "ID_GROUP_0" ]
}

(NOTE: This globalId is NOT a proposal, but only an overly suggestive workaround to get the idea across. The question of how to establish such references cleanly is not easy to sort out. It might be similar to one of the options in #558 (comment) , but I haven't yet wrapped my head around the latter...)


On the level of the implementation, one question is how this metadata should be accessed. The getPropertyInherited method that was already linked to leaves some questions unanswered. For example, referring to the diagram, calling

contentMetadata.getPropertyInherited("name")

would return "Manhattan" (which is the name of the tile), but there is no reasonable way to access the name of the tileset. This could, roughly speaking, be solved by not merging the metadata into a single, flat structure, but to explicitly keep the metadata in the structure in which it is defined and obtained on the client side. There currently is an (internal) interface called MetadataEntity, that roughly looks like this:

interface MetadataEntity {
   MetadataClass class();
   String[] getPropertyIds();
   Object getProperty(String propertyId);
};

(Yes, it's Java syntax, but it is just so clear and simple this way...)

On the interface/API level, this structure could just be extended with a function like

MetadataEntity[] getParents();

In this case,

  • contentMetadata.getProperty("name") would return undefined
  • contentMetadata.getParents()[0].getProperty("name") would return "Manhattan"
  • contentMetadata.getParents()[0].getParents()[0].getProperty("name") would return "New York City"

thus, leaving the structure of the metadata intact, and avoiding ambiguities.


An aspect that is related to this discussion, but may be orthogonal, is: How to know what a certain Metadata entity is associated with? One could pragmatically throw in some of the obvious options here, like defining an enum OwnerType { TILESET, TILE, GROUP, CONTENT, ... } and storing a metadataEntity.ownerType = TILE, but the devil is in the detail, and this may warrant some discussion in a dedicated issue at some point.

@javagl
Copy link
Contributor

javagl commented Mar 7, 2022

Extending the closing thought from the previous comment:

An aspect that is related to this discussion, but may be orthogonal, is: How to know what a certain Metadata entity is associated with?

There is one aspect about the answer of this question that I find crucial: Iff a metadata entity knows what it is associated with, then how exactly does it know this? I could think of three different ways of representing some structural information:

1. Each metadata entity could just have a value that indicates its "owner type". (The "owner type" could even be a plain, application-defined string. That's a detail for now.)

// Returns OwnerType.TILESET, for example
OwnerType ownerType = metadataEntity.getOwnerType(); 

2. Each metadata entity could have a reference to the metadata of its parent (or a list of metadata objects, for "multiple inheritance" - also a detail for now)

// Called on the metadata of a tile, this returns the metadata of the tileset:
MetadataEntity tilesetMetadataEntity = tileMetadataEntity.getParent(); 

3. Each metadata entity could have a direct reference to the owner itself:

// Called on the metadata of a tile, this returns the 'tile' object:
var owner = metadataEntity.getOwner(); 

The last one is problematic, obviously: It's competely untyped, and cannot be specified in any way. It might as well be like that in the implementation (e.g. in CesiumJS). But it's crucial to not use this to accomplish things that can not be accomplished with the part that is specified. This is just one of the thoughts that are relevant for the question of how exactly "inheritance" of metadata can be modeled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants