Code Monkey home page Code Monkey logo

specs's People

Contributors

athelena avatar balazsdukai avatar clausnagel avatar fbiljecki avatar ginastavropoulou avatar hugoledoux avatar jliempt avatar kenohori avatar kkimmy avatar liberostelios avatar zoelandia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

specs's Issues

Misleading ADE documentation

I just read through the Extensions chapter of the CityJSON 0.8 specification on http://www.cityjson.org and came across the following:

While Extensions are less flexible than CityGML ADEs (ie they have a narrower scope and less customisation is possible), it should be noted that the flexibility of ADEs come at a price: standard software (eg viewer or spatial analysis software) will not process correctly the files containing ADEs since specific code needs to be written.

I would not agree with the "specific code needs to be written" part of this statement. It really depends on how the parser is implemented. It is, of course, possible to implement a generic GML parser that can handle arbitrary GML schemas. Since both CityGML and ADEs are just GML schemas, such a parser would be able to read ADE-enriched CityGML datasets without having to write any specific code.

There is software using generic GML parsers such as FZKViewer or FME, or libraries such as GeoTools or GDAL. Both FZKViewer and FME, for instance, can read and visualize ADE datasets without additional code.

There is also software for which the statement is true such as the citygml4j library. But this is not because of a general limitation of ADEs, but rather because citygml4j uses an XML binding approach instead of a generic GML parser. And, of course, it's the same in the JSON world: if you use a JSON binding approach to derive classes from the core CityJSON schemas, then support for any CityJSON Extension would require specific extra code to be written.

Hashes as city object IDs

Why?

Currently, IDs of the city objects are meant to be any kind of unique identifiers without any restrictions. Messing around with different open datasets, I haven't seen a meaningful and functional use of the identifiers so far.

Instead of leaving this free to the implementation, I propose that we use hashes of the city object content as their IDs. This means that the hash can be representative of the city object. If something changes in the city object (geometry or attribute), then the hash changes as well.

That adds a lot of possibilities:

  • It can be used to validate the data integrity of city objects served on the web (which is one of the main aims of CityJSON). That could be extremely useful with regard to future plans for a web tiling scheme.
  • It allows us to do a lot of interesting tricks regarding the indexing of city object data. For instance, we can exploit hashes in order to keep track of versions and differences between objects (same as git uses hashes for storing versions of files).

How?

A simple solution would be by simply hashing the string of the JSON encoding of the city object as it is today. That would make the hash, though, fragile against small changes (such as alteration to the CityJSON attribute names). There are many other possibilities which could be discussed. But the idea is that it should be very concrete what the hash function input is, so that developers always implement it in the same way.

Pros

  • IDs are becoming meaningful, functional and consistent. Everyone knows what they are and can use it in order to validate and manipulate the content of the model.
  • ID uniqueness is ensured. Of course, hashes conflicts are possible in theory, but current applications of the mechanism provide proof that it is impossible in practice.

Cons

  • Adds a little more complexity on the implementation. But implementing a hashing functionality should be pretty straightforward for developers, as soon as the rules of hashing are concrete. If it's considered to be that complex, we could still propose it as an optional functionality.
  • Might make alterations of the schema on future versions more difficult, as the changes can affect the hash outcome. The idea of the ID being a hash is that we can know that two different hashes refer to two different city objects (or two different versions of the same city object). The notion that an unchanged city object can have a different hashes just because the schema has changed, breaks the original purpose. But that could be somewhat minimised if the hashing mechanism doesn't rely on the exact encoding, but on a more stable representation of the city object. Or, by simply accepting that two different CityJSON versions of the same city object can have different hashes.

Clarify how to nest children of CityObjects

It was not completely clear for me what can I expect in the children array of a 1st-level CityObject. Whether the array contains all the COs. that are related to it (children of children), or just those that are one level below (only immediate children).

My interpretation of the current specs is that the second is true. I opened a PR ( #48 ) to support this by making the description and example more explicit. Please correct me if I'm wrong.

Metadata Notes

-there seems to be a slight misunderstanding and I thought we had changed it but it shouldn't be semanticClasses but thematicModels, because otherwise I get confused about them not being windows and doors, etc
-metadataPointOfContact is not ISO it's the metadata creator so in this case the same as the contact for the dataset
-metadata date stamp is also the creation date of the metadata
-metadata standard name is 'ISO 19115 - Geographic Information - Metadata'
-metadata standard version is 'ISO 19115:2014(E)'

Relation between openings and boundary surfaces

Boundary surfaces such as wall or roof surfaces as well as openings such as doors and windows are both modelled as elements of the semantic surfaces array as shown in the following example:

 "semantics": {
  "values": [ ... ],
  "surfaces": [
   {
    "type": "Window"
   },
   {
    "type": "WallSurface"
   }
  ]
 }

Now, typically, a window or door belongs to a wall or roof. But this relation is not explicit in the current encoding. Thus, a query like "get all doors belonging to a given wall" cannot be answered directly but requires additional knowledge. This knowledge could be derived, for instance, from a spatial check, which however requires clean geometry and might be expensive.

It would therefore be great if this knowledge would be directly available. One solution could be to specify that a "Window" or "Door" belongs to that boundary surface (e.g. "WallSurface" or "RoofSurface") which is its direct predecessor in the "surfaces" array. The above snippet would therefore be invalid because the "Window" does not have a predecessor.

Another solution could be to use the "parent" and "children" properties introduced with CityJSON 0.8 (using the array index as value). For example:

 "semantics": {
  "values": [ ... ],
  "surfaces": [
   {
    "type": "Window",
    "parent": 1
   },
   {
    "type": "WallSurface",
    "children": [0]
   }
  ]
 }

This relation is also relevant when mapping CityJSON to CityGML. Typically <Window> and <Door> are given as nested elements of their boundary surface, such as:

<bldg:WallSurface>
 <bldg:opening>
  <bldg:Door>
   ...
  </bldg:Door>
 </bldg:opening>
</bldg:WallSurface>

For citygml4j, I have implemented the first solution simply because "parent" and "children" have not been available before 0.8. But I would prefer that CityJSON states how to derive this relation or at least recommends a best practice.

update to metadata

There's a couple of things for the three of us to discuss next week but for initial changes:
-there seems to be a slight misunderstanding and I thought we had changed it after you commented on it for the paper but it shouldn't be semanticClasses but thematicModels, because otherwise I get confused about them not being windows and doors, etc
-metadataPointOfContact is not ISO it's the metadata creator so in this case the same as the contact for the dataset
-metadata date stamp is also the creation date of the metadata
-metadata standard name is ISO 19115 - Geographic Information -Metadata
-metadata standard version is ISO 19115:2014(E)

--> specs.rst, example-metadata.json, metadata.json (schema) all need to be updated

No attributes for boundary surfaces

Thanks for drafting CityJSON. Just scanned the schema and examples. It seems that CityGML's concept of thematic boundary surfaces such as WallSurface or RoofSurface has been reduced to labels associated with geometric surfaces. This prevents storing attributes with individual boundary surfaces. For many CityGML models I have come across this will mean losing information when using CityJSON.

Might be worth thinking about a general pattern for representing sub-features with their spatial and non-spatial properties.

Btw, the example dataset at http://www.cityjson.org/en/0.1/_downloads/3-20-DELFSHAVEN.json uses the label "Wall" while the specification defines the label "WallSurface" (http://www.cityjson.org/en/0.1/specs/#semantics). Should be defined in the schema to enable interoperability.

texture files must be local?

The specification at Appearance Object states that "texture files have to be local and put in folder named "appearances" located in the same folder as the CityJSON file (thus requests to web services as is the case with CityGML are not supported)."

Then it states that a Textrue Object "must have one member with the name "image", whose value is a string with the name of the file. This file can be a URL (eg "http://www.hugo.com/filename.jpg"), a relative path (eg "appearances/myroof.jpg"), or an absolute path (eg "/home/elvis/mycityjson/appearances/myroof.jpg")."

Which one is true?

todo re: Extensions

  • do we enfore a "namespace" for extra attributes? By have like "+Noise-attribute". This would avoid clashes between diff Extensions, but makes the whole thing more complex.
  • where are the extensions files? If they are in a subfolder of schemas /extensions/ then it means that for CityJSON types to be reused one must write have relative path ../cityobjects.json
  • rename schemas to cityjson.schema.json, like glTF does?
  • make a schema to validate a cityjson extension

CityObjects in sorted order

Sometimes it is useful to sort city objects by their thematic (or spatial) attributes such as height, address or name. The OGC WFS 2.0 interface, for instance, allows clients to request features in a sorted order using the <fes:SortBy> element of query expressions. Formats like GML or GeoJSON have FeatureCollections that are defined as arrays and thus preserve the order of the contained features.

The "CityObjects" property in CityJSON is a JSON object and thus an unordered set. As a consequence, JSON libraries are free to rearrange the order of the elements.

I am struggling with this in the context of the 3DCityDB WFS, which is capable of serving CityJSON data. If a client requests city objects in a sorted way, the order gets lost in the CityJSON output. My current hack is to add a "sequenceId" attribute to each CityObject so that a client could potentially rebuild the original order. It would be easier for the client to just read the objects from the file and be sure they are properly ordered.

Of course, the current "CityObjects" property makes it easy to programmatically access city objects by their ID. Well, just wanted to point to this issue and start a discussion.

LoD concept for CityObjectGroup unclear

A CityObjectGroup can currently have an LoD specification under geometry, but it's not clear if this is the LoD of the polygon, which is an issue as there is currently no definitions of these LoDs, or the LoD of the members, which also doesn't make sense because the members could have multiple different LoDs amongst themselves.

"CityObjects": {
  "my-neighbourhood": {
  "type": "CityObjectGroup",
    "members": ["building1", "building2"],
    "geometry": [{
      "type": "MultiSurface",
      "lod": 2,
      "boundaries": [ [[2, 4, 5]] ]
    }]
  }
}

How to get Latitude/Longitude

How do you get the latitude/longitude and height from a valid cityjson?

Example

Download NewYork.zip from here

Unzip

import json

blob = json.load('DA13_3D_Buildings_Merged.json')

blob['metadata']
# {'geographicalExtent': [985320.346, 219464.155, -1.5, 1009996.302, 259992.617, 677.862]}

blob['transform']
# {'scale': [0.001, 0.001, 0.001], 'translate': [985320.346, 219464.155, -1.5]}

example_building = 'gml_7KKGXJDCBAXCTELB70OMHK04I376NBA6NGHC'
example_city_obj = blob['CityObjects'][example_building]
# {'type': 'Building', 'attributes': {'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, 'geometry': [{'type': 'MultiSurface', 'boundaries': [[[327517, 327518, 327519, 327520, 327521, 327522, 327523, 327524, 327525, 327526, 327527, 327528, 327529, 327530]], [[327531, 327532, 327533, 327534, 327535, 327536, 327537, 327538, 327539]], [[327540, 327541, 327542, 327543, 327544, 327545, 327546]], [[327544, 327543, 327532, 327531]], [[327530, 327531, 327539, 327517]], [[327529, 327545, 327544, 327530]], [[327528, 327546, 327545, 327529]], [[327527, 327540, 327546, 327528]], [[327526, 327541, 327540, 327527]], [[327525, 327542, 327541, 327526]], [[327524, 327543, 327542, 327525]], [[327523, 327533, 327532, 327524]], [[327522, 327534, 327533, 327523]], [[327521, 327535, 327534, 327522]], [[327520, 327536, 327535, 327521]], [[327519, 327537, 327536, 327520]], [[327518, 327538, 327537, 327519]], [[327517, 327539, 327538, 327518]]], 'semantics': {'values': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 'surfaces': [{'type': 'GroundSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'RoofSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'RoofSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}, {'type': 'WallSurface', 'SOURCE_ID': '13210006270', 'BIN': '1061273', 'DOITT_ID': '168309'}]}, 'lod': 2}]}

From my understanding, each of the geometry.boundaries is an index for the blob.vertices, so to get the vertex for the first element of the first boundary above 327517, we can do

blob['vertices'][327517]
# [13360760, 19999727, 122068]

Based on the cityjson spec, we also now need to use the blob.transform on that.

x_in, y_in, z_in = blob['vertices'][327517]
x_out = (x_in * blob['transform']['scale'][0]) + blob['transform']['translate'][0]
y_out = (y_in * blob['transform']['scale'][1]) + blob['transform']['translate'][1]
z_out = (z_in * blob['transform']['scale'][2]) + blob['transform']['translate'][2]
x_out, y_out, z_out
# 998681.106, 239463.88199999998, 120.568

This is not a lat/lon/height, so am I doing something wrong or are there additional steps in order to get the latitude and longitude?

Thanks in advance for any help!

MultiPoint of address requires "lod" property

The "location" property of a building "address" is defined to be a "MultiPoint" geometry. As per definition in the v0.3 schema, a "MultiPoint" requires an "lod" property.

Whereas "lod" is important for spatial properies of features, having different LoDs for the location of an address does not make too much sense.

Imho, the "lod" property should remain mandatory for feature geometries. Hence I suggest adding a new "LoD-less" multi point geometry for addresses.

Attributes for CityObjectGroup

All City Objects have at minimum the following five attributes: creationDate, terminationDate, class, function, usage. Only CityObjectGroup seems to differ as it lacks the first two. What is the rationale behind this difference?

Parent Property Energy Extension

The switch over from the "parent" to the "parents" attribute as well as the introduction of the new "toplevel"attribute (as discussed in Issue #38) seem not to be incorporated in the schema files of the Energy Extension.

When I try to validate a file in cjio according to the Energy schema file e.g. "parent": "string"
I get: KeyError: 'parents'

When I try to do it according to the docs v0.9 e.g. "parents": [array] I get the error: Additional properties are not allowed ('toplevel', 'parents' were unexpected)

Also, is the "toplevel": Boolean to be used within the "attributes" or the "geometry" property, because in the docs/extensions in paragraph "2. Creating/extending new City Objects" the attribute is written in the "attributes" property and in the last paragraph "Adding complex types for CityFurniture" the attribute is written in the "geometry" property.

Side-question regarding the Energy extention:
Is the energy-physics.json schema file still needed? As far as I get it from what is written here, the mechanism for extending the AbstractBuilding type with the energy-attributes has been revamped so that +AttributeName within the normal building type is now to be used and not the +EnergyBuilding type anymore.

Otherwise thank you for all the great work so far, I find this encoding a lot more comprehensive and easier to handle than its gml counterpart.

Semantic Surface children and parent

Since there is only a one-to-many relationship between semantic surfaces (just like in case of CityObjects), do we need to explicitly define the child --> parent relationship (eg. blue Door in example), or is defining child <-- parent enough (eg. red Door)? What is the reason for having both "children" and "parent"?

I see the existence of both "children" and "parent" property as an invitation for inconsistency, just like @clausnagel in his 3rd point in #38 . Also it means that one needs to double check the links between children and parents to make sure all relationships are discovered.

Furthermore, if the "parent" property is needed, does it make sense to harmonize it with the CityObject's "parentS" property, which is an array? Even though it would be an array with a single element most (all) of the cases.

{
  "type": "MultiSurface",
  "lod": 2,
  "boundaries": [
    [[0, 3, 2, 1]], [[4, 5, 6, 7]], [[0, 1, 5, 4]], [[0, 2, 3, 8]], [[10, 12, 23, 48]]
  ],
  "semantics": {
    "surfaces" : [
      {
        "type": "WallSurface",
        "slope": 33.4,
        "children": [2,3]
      }, 
      {
        "type": "RoofSurface",
        "slope": 66.6
      },
      {
        "type": "Door",
        "parent": 0,
        "colour": "blue"
      },
      {
        "type": "Door",
        "colour": "red"
      }
    ],
    "values": [0, 0, null, 1, 2]
  }
}

Are new semantic surfaces listed in "extensions" member?

The CityJSON extension mechanism allows adding new semantic surfaces by simply adding "+" to their name. My question is whether these names also have to be listed in the "extensions" member of the "CityJSON" object? The current specification only says that new City Objects are to be listed there.

Why using an indexed scheme instead of a "feature-approach”?

One of the main criticism/discussion-point/question is that CityJSON uses, for the geometries and textures, an "indexed scheme" instead of a "feature-based approach". An indexed scheme means that the coordinates (x,y,z) of the vertices are given in a separate list, and that the geometries refer to the indices of the vertices. In contrast, a feature has all its coordinates listed directly in its geometries (à la GML).

There are obviously pros and cons in having an indexed scheme, and I drafted here below a list as a starting point for discussion. Please contribute.

Cons of indexed scheme

  • Streaming/sending of features is more cumbersome as a feature is not 'self-contained'. A large CityJSON file needs to be split into smaller files since the list of vertices can become very large.

  • This means that CityJSON files to be pre-processed, and if a subset of the features is selected then the indices need to be updated. It should also be said that splitting a file into a subset, or merging many into one file, is a rather simple operation and is already implemented and fully working, see cjio which can be easily installed on all systems.

  • Observe however that for CityGML, if one wants to WFS/stream a dataset, she needs to "pre-process" it too, because many 'generic' properties can be encapsulated into one given feature, eg:

    • resolve+replace XLinks for shared surfaces and other uses
    • deal with Implicit Geometries: find in the file + replace

(CityJSON avoids these by having a global list of Implicit Geometries, and there are no XLinks)

Pros

  • More human-readable files. People can compare indices, slightly different numbers with many decimals not so much
  • We can use 'topology' in file to do tests (adjacency, shared vertex, incidence, etc)
  • Closer to visualisation formats (OBJ, OFF, glTF), as they too use indexed schemes. Can thus be directly translated to efficient representations for graphics APIs (eg IBOs in OpenGL/WebGL).
  • Going from index- to feature-based is trivial, the other way around less so.
  • More compression in general (based on some tests with CityJSON and that script we get ~1.8X compression with an indexed-scheme, which not neglibeable).
  • Textures are local/per-object in CityGML (<appearance> tag), but I see an advantage in listing only once the textures and not repeating the path of the texture for each surface

Attribute extensions

The CityJSON extension specification discusses two possible alternatives for adding new attributes to a City Object: 1) simply add the new attributes to the "attributes" property, or 2) define a new City Object (recommended).

Things get tricky if you have two or more extensions that want to add new attributes to, for instance, a "Building", and if you want to share them in one CityJSON file. Option 1) will fail if attributes from one extension happen to share the same name with predefined CityJSON attributes or attributes from another extension. You would have to adapt their names just for being able to exchange them. Option 2) will not fail but you would have to exchange, for instance, a "+NoiseBuilding" and an "+EnergyBuilding" with all the same "geometry" and "children" and so on. I think this is a huge overhead if you just want to add some noise and energy attributes.

So I would like to propose another solution. Why not allow adding a new property for each extension, which then contains all additional attributes from this extension for a predefined City Object? To be consistent, the names of these new properties should also start with a "+". For example:

{
  "type": "Building",
  "attributes": { ... },
  "+noise-attributes": {
    "level": 1,
    ...
  },
  "+energy-attributes": {
    "level": "AAA",
    ...
  },
  "geometry": [...]
}

The benefit is that predefined CityJSON attributes in "attributes" and attributes from the different extensions are nicely seperated, which avoids name clashes. And you do not have to define multiple City Objects just for attributes. Furthermore, the additional properties like "+noise-attributes" or "+energy-attributes" could be defined in their own JSON schema.

You could also wrap those attribute containers by another predefined property:

{
  "type": "Building",
  "attributes": { ... },
  "extension-attributes": [
    "+noise-attributes": {
      "level": 1,
      ...
    },
    "+energy-attributes": {
      "level": "AAA",
      ...
    }
  ],
  "geometry": [...]
}

This adds an extra level of nesting to the data structure and thus is more verbose. But the positive aspect is that "extension-attributes" is defined in the CityJSON schema. It would thus be the only extension point for adding new attributes to a predefined City Object. So this might be helpful for implementers, as they would only have to check "extension-attributes" for additional attributes.

Supporting signatures

would you consider supporting signatures of cityJSON files, for instance using the Jason Web Signature standard (https://www.rfc-editor.org/rfc/rfc7515.txt)? This would be a nice feature that enables a user to verify the authentic source of a city JSON document regardless of the way he acquired it.

Add bbox property to city objects

Would be nice to have an optional "bbox" property on all city objects like Building, Bridge, etc.

One use case I have in mind is light-weight responses to queries. For some applications, I need to retrieve city objects from a CityGML datastore according to some spatial or thematic filters. But I am only interested in the number, type and thematic properties of the matching city objects, not in their possibly heavy-weight geometry.

CityJSON allows skipping the geometry, which helps in reducing the file size and thus in having fast responses to queries. However, when skipping the geometry there is no further spatial information about the city objects. With a "bbox" property you still would have light-weight spatial information per city object (which you could use, for example, to fly to the object on a web map).

Allow vendor-specific properties for the root "CityJSON" object?

The current JSON schema disallows any properties on the root CityJSON object besides the predefined ones.

Relaxing this limitation would allow adding vendor-specific properties that are neither covered by the predefined ones nor by the metadata element. Parsers can simply ignore these additional properties if they do not know how to deal with them.

Flattening addresses

I think we should flatten addresses into a single string using local formatting conventions. Rationale:

  • Addresses are the only built-in nested attribute in CityJSON
  • The address schema (from xAL) lacks fields that are needed to uniquely identify an address in many countries (e.g. toevoegsel in NL, building number/name, multiple levels of administrative subdivisions, etc.)
  • The schema doesn't fit at all with how some countries format addresses (e.g. Japan and South Korea)
  • A string with full address can be geocoded, but it's difficult if you don't know the right order to put the fields (which differ by country)
  • Simpler is better!

Allow remote references to texture image files

As for the current version of the specification, all texture image files are required to be in a local folder named "appearances" located next to the CityJSON file, and the "image" member of a texture object may only carry the name of the texture file.

Placing a large number of files in the same folder may cause troubles for some file systems. It would thus be good to allow organizing the texture files in subfolders below "appearances", which requires storing relative paths in the "image" property.

However, local references to texture files are not sufficient if you want to serve CityJSON via a web service (well, at least if you do not want to create some sort of ZIP container at the server side). So it would even be better to allow both local and remote URI references to texture image files.

"lod" should be string

Since "lod" supports the improved LoDs, it is not a good idea to store it as a number because of floating-point intricacies. Once parsed, the actual number stored in memory will not be the same, and so simple tests like "lod" = 3.3 might fail. Much safer to store as a string.

LoD 1.1 stored as a float: 1.10000002384185791015625
LoD 3.3 stored as a float: 3.2999999523162841796875

Wrong name and type of storeysHeightsAboveGround and storeysHeightsBelowGround

The attributes "storeysHeightsAboveGround" and "storeysHeightsBelowGround" of Building and BuildingPart defined in the v0.2 Json schema have a wrong name compared to the their CityGML counterparts. It should be "storeyHeights..." - so no plural for storey.

Moreover, also their type differs. In CityGML, both attributes are of type gml:MeasureOrNullListType, whereas they are defined to be of type integer in CityJSON. An array of double would be more appropriate.

Remove "parent" property?

2nd-level CityObjects like "BuildingInstallation" offer a "parent" property of type string which is the ID of the parent CityObject. It is assumed that every 2nd-level CityObject has exactly one parent, and this is fine for the CityJSON core objects.

But what about extensions? The EnergyADE, for instance, defines a feature type called Construction to define the structure, material and energy-related properties of walls or roofs. As many walls in a building are of the same type, their Construction only needs to be defined once in a dataset and then can be reused by the different wall objects. This also helps to keep the file size small.

So, when mapped to a CityJSON extension, "Construction" would be an example of a CityObject having multiple parents. A simple string would not be sufficient anymore. I see three possibilities to solve this:

  1. Keep the restriction that a CityObject can have at most one parent. As a consequence, CityObjects like "Construction" cannot be reused. Instead, every wall would have to reference its own "Construction" copy as child even if all these copies would have identical properties and values. This would also increase file size.

  2. Redefine "parent" to be an array of strings to be able to reference the IDs of multiple parents.

  3. Completely remove the "parent" property from all CityObjects. As a consequence, the bi-directional associations between CityObjects would become one-directional (from the parent to the child via the "children" property).

I propose option 3. When reading a CityJSON dataset into main memory, it is really simple to internally create pointers from a child to its parent(s) based on the "children" property in case an application really needs to navigate associations in both ways. Moreover, having both "children" and "parent" as properties in the dataset increases the possibility of inconsistencies between them.

Material/texture questions

The v0.2 Json schema only defines "material" and "texture" properties for the geometry types Solid and MultiSurface . What about CompositeSurface, MultiSolid and CompositeSolid? In CityGML, also their surface members can receive appearances.

What about the depth of the arrays of "material" and "texture" for each geometry type? According to the examples in the spec, "texture" seems to have the same hierarchial structure as "boundaries", whereas "material" seems to be a flat array. Is this correct? Would be great to have these definitions in the Json schema as well.

Often not all surfaces of a building shall receive a material or texture. Just think of the GroundSurface, which is not visible in most viewers anyways. How do you denote non-colored resp. non-textured surfaces in the "material" and "texture" arrays?

add support for <grp:CityObjectGroup>?

on another channel, @clausnagel and I discussed <grp:CityObjectGroup>, see citygml4j/citygml4j#10

The question is: should we add support for them in CityJSON? The proposal of Claus is simple and doesn't affect any parsers, just that the type should be ignored. I'm in favour, although it's seldom used in practice it seems.

Claus' solution

introduce a new CityObject type:

"CityObjects": {
  "id_01": {
    "type": "CityObjectGroup",
    "parent": "id_of_parent",
    "members": ["id_of_member_1", "id_of_member_2", "id_of_member_3"] 
  }
}

So the CityObjectGroup would basically just list its parent and members by gml:id. Would make the group more explicit and possibly more easy to query. In CityGML, a group can even have geometry, so this could also be represented in CityJSON if the group is represented in this way.

Cannot read v8 schema using Altova XMLSpy

Altova XMLSpy is a very useful tool for working with JSON files and JSON schemas. When I load in the v8 CityJSON schema, Altova XMLSpy cannot follow the external schema links:

xmlspy_68erxj17eq

I am not sure if this is a limitation of XMLSpy or if the CityJSON schema is not correct. Any of the following solutions would work for me:

  1. Find another graphical schema editor (do you have any suggestions?)
  2. Use a script to combine all the schema's together (does such a script exist?)
  3. Change the CityJSON schema to meet Altova XMLSpy's requirements

Do you have any recommendations?

Should "extensions" have a version property for every listed extension?

Currently, the "extensions" property lists the URLs of the definitions of the extension contained in a CityJSON file. While the definition of the extension contains a "version" property, the file doesn't specify explicitly which version of the extension it is implementing.

Obviously, the URL points to a definition of a specific version of an extension, therefore one can argue that it might be redundant to add it in the file itself. If I am pointing to the URL of Noise extension v0.1, why should I specify it in the file itself? From a developer's perspective, though, having to fetch and parse the definition file in order to determine the version of the extension that the file is using adds a lot of unnecessary complexity (and overhead).

I suggest that the list of extensions should have not only the URL, but the version of the extension that this file implements. This way, it's easier for a piece of software to validate whether it can parse a file or not.

For example:

"extensions" {
  "Noise": {
    "url": "https://someurl.org/noise.json",
    "version": "0.1"
  }
}

Btw, shouldn't the "extensions" property be an array instead of an object?

Chunk-wise parsing/writing of CityObjects

The current layout of a CityJSON dataset requires access to the "vertices" array in order to be able to process a city object. This hinders implementing a streaming parser that would be able to read city objects as individual chunks. Benefits of a chunk-wise parsing approach would be, for instance, that you do not have to read the entire CityJSON dataset into main memory but that chunks can already be forwarded to other threads for processing while the dataset is still being read.

And chunk-wise processing might also be beneficial when compiling a dataset. For example, think of a webservice such as a WFS that responds with a CityJSON dataset to a client request. Although individual CityObjects can be constructed and send as a stream to the client with the current CityJSON schema, the WFS implementation would always have to keep the entire "vertices" array in main memory and could only send it after the last city object has been sent to the client. If a client requests large parts of a city model, then the "vertices" array might quickly grow in size and eat up resources. Likewise, although the client could read the individual city objects from the stream, it would only be able to really process them after the "vertices" array has also been received.

A possible solution to this would be to let each city object have its own "vertices" array (same for "material" and "texture"). So all information about the city object would be contained in one Json object.

Well, this is of course a design decision. And there are also reasons for having one common "vertices" array, e.g. non-redundant vertices over all city objects.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.