CVE "Scalable Dataspace" notes
Bulk-loading of static and dynamic content in MOOsburg is a potentially
significant problem, particularly if we consider growth of the underlying
datasets as MOOsburg is adapted to new applications.
Bulk-loading not only slows startup over slow connections, but also increases
client-side memory
footprint, thereby degrading responsiveness under constrained
memory conditions.
Aside from performance and efficiency concerns, the current implementation(s)
of data loading in MOOsburg present flexibility constraints:
-
Implementing different datasets and renderers for different clients is
difficult.
(e.g., consider porting existing moosburg gui to a low-memory, small-screen
handheld)
-
Separate mechanisms are used to store and render GIS-derived map data,
landmark visuals, and space visuals (e.g., nested interior maps).
-
Knowledge of specific dataset characteristics is embedded in renderer code.
A proposed step towards correcting these problems is to define
generic abstractions for renderable entities with MOOsburg and future
CVEs.
The goal is to design an architecture that efficiently supports multiple
viewpoints into a large heterogeneous database of static and dynamic
renderable entities.
Such entities in MOOsburg currently include:
-
Static road and building data
-
Landmark and space data
-
Landmark graphics (e.g., for grocery stores)
-
Landmark visual descriptions (whiteboard objects and images)
-
Space maps
-
Landmark contents (objects and avatars)
And more trivially:
-
Toolbox contents
-
Inventory contents
Future MOOsburg and NAVCIITI development work could include the following
types of renderable entities:
-
Manually-added additions/corrections to static map data (e.g., adding new
buildings)
-
Stream data.
This is supported in the current MOOsburg client but the dataset is far too
large to load in bulk.
-
Historical datapoints
-
Specimen data (e.g., for the MuseIT scenario)
For items in each set of data we have:
-
The underlying "raw" data itself, e.g., coordinates of a line segment on
a map, a MOOsburg
GenericCharacter object, etc...
-
One or more objects that encapsulate logic for rendering and
interacting with a single specific item, e.g., a
LandmarkComponent on a map, an
Avatar object, etc...
-
One or more objects that encapsulates the logic for rendering multiple
items from one or more sets of data, e.g., the MOOsburg map (which shows
several sets of static map data as well as landmark data), landmark viewer,
landmark editor, etc...
Here is a proposed set of classes/interfaces:
-
Renderer
-
Renderers support displaying specific kinds of objects.
The set of supported object types should be publically accessible.
Hence a zoomable map view (based on the current MB map) might support
rendering of landmark data and static/dynamic map elements.
(Do we need a separate abstraction for objects that render specific,
individual objects? Are these likely to be generally reusable between
different aggregate renderers?)
-
Viewpoint
-
Viewpoints describe the current field of view available in a renderer.
More thought needs to be given to this to ensure that Viewpoints are
as generic as possible.
It might be sufficient to have Viewpoints provide:
-
The renderer's "root" object
-
The user's position in a standard or convertable coordinate system
-
The orientation and size of the user's field of view
In the initial implementation Viewpoint simply contains
the "world" bounds, the bounds of the user's field of view (in the
world coordinate system), and the dimensions of the rendered representation
of the user's field of view.
-
RenderableSet
-
A dynamic set of renderable objects.
RenderableSets should provide:
-
Means for a renderer to enumerate their elements
-
Means for a renderer to be notified when elements are added to or removed
from the set
-
Means for the renderer to dispose of the set, e.g., when a change in
viewpoint invalidates it
Should these be mutable? e.g., for renderers that are also editors?
-
RenderableSetFactory
-
RenderableSetFactories generate RenderableSets of specific kinds of objects
based on a renderer's viewpoint.
CVE behavior could then look like:
-
A CVE would be configured with a set of Renderers and a set of
RenderableSetFactories.
-
Each Renderer inspects the available RenderableSetFactories and determines which
provide access to objects that it knows how to render.
(The set of RenderableSetFactories available to each renderer could also be
constrained by configuration.)
-
Each Renderer queries each relevant RenderableSetFactory, passing in its
current Viewpoint and getting back an RenderableSet.
The renderer attaches a listener to each RenderableSet to discover when objects
are added or removed.
Depending on the type of object, it may also attach listeners to invidual
objects in an RenderableSet.
-
When a repaint is needed, the objects in each RenderableSet are iterated over
and rendered.
-
When the Renderer's viewpoint is changed, the current RenderableSet(s) are
discarded and the relevant RenderableSetFactories are again queried with
the new viewpoint.
It is the responsibility of the RenderableSetFactory to implement an appropriate
caching mechanism.
Things we need to consider:
-
How general can we make Viewpoint representations?
Perhaps just a set of these: one for local field of view, one for
"birds-eye"/map view?
-
Reconciling different coordinate systems.
-
Implications of scriptable RenderableSetFactories and Renderers
-
Generic RenderableSetFactories for annotating data accessed through other
RenderableSetFactories
Map data configuration
To handle dynamic loading of potentially large quantities of static
map data (e.g., from Shapefiles), pointers to data files could be
pulled out into a configuration file, with one entry per data file
containing:
-
category
-
A human-readable category name.
This could be used in conjunction with user preferences to enable and disable
different data sets.
-
min_magnification
-
Minimum magnification level at which the client should consider loading the
data.
(Do we need
max_magnification as well? Are
there sets that will only be rendered at low magnification?)
-
x, y, w, h
-
Bounds of the data.
-
url
-
URL for the datafile
-
-
color
-
Color that data in the set should be rendered in.
(Are there other "rendering hints" do we need in addition to color? In
the initial implementation we do not include this in the config file -- instead
we set it when we contruct the renderer. We also specify whether polygons
should be filled when rendered.)
In MOOsburg, the top-level roads would have
min_magnification
such that they were always drawn, and bounds that were the size of "world view".
Buildings could be would have a higher
min_magnification
and be split into perhaps 16 files, corresponding to a 4x4 grid.
This would get the size of any given chunk of data under 100K.
Similarly, ponds could be split into 25 or 36 chunks.
Dynamic Data: spots and structures
As with static map data, dyanamic data (replicated objects describing
spots and structures) should not be loaded until the user's viewpoint (field of
view and magnification) make it visible.
Issues include:
-
Should content within structures (buildings) be included in the class for (e.g.)
"outside" content, or should it be contained within "structure" class
which is then contained in the "outside" class?
- + A unified representation of all content would simplify
promotion/highlighting of interesting content within buildings
- + and might also simplify exhaustive searches
- + A flat structure might simplify selective loading of content for
a given viewpoint. When the user zooms in, we will probably want to load
most or all of the data for spots inside of buildings (or at least one
spot per floor), so that we are not trying to do that when the navigation
popup appears.
- - but buildings will need separate metadata anyway (number of floors,
map modifications, etc...)
- - but would complicate rendering of building maps
- - but would complicate distributing replicated content across multiple
servers, at least in our current conception of how such distribution would
occur.
We have assumed that distribution would be done by discrete geographical
units (e.g., by building), but perhaps distributing by "layer" would make
more sense.
This would allow external entities to serve their own content that existed
at the top level or within buildings.
This might simplify "policing" of content, since loading or subscribing
to a specific externally-served layer might involve a login/confirmation
step with warnings about size and ownership of content.
We could provide basic map, login, and landmark services (as well as
layers for applications like ROLE or the Vis Programming project), and allow
others to create, register, and maintain other arbitrary layers.
Note that even in a "flat" structure, content would still be conceptually
hierarchical, since content would have pointers (of some sort) to the
structures that they were contained in.
As of 010914 the implementation uses a flat representation.
Content within a structure is currenly distinguished by having a non-zero
value for the level property.
-
How do we associate the outline of buildings from the map data to dynamic,
replicated objects describing the building layout and contents?
Options include:
-
Add an identifier to each building outline in the shapefile dataset.
This identifier would be stored in the replicated object that represents
a populated building.
-
- This will increase download size
Or not: there is already a feature id in the shapefile that we may be
able to re-use.
We could also compute the feature id (based on index within the file) after
download.
-
- Lookup could be expensive
(feature id distribution is unlikely to follow "chunk" boundaries in
a useful way, though since we're creating the chunks we could probably
change the feature ids, or compute them from chunk and shape indices.)
-
Use the building coordinates as an identifier.
The coordinates would be stored in the replicated object that represents
a populated building.
-
+ This will not increase download size
-
- Lookup could still be expensive
-
Add ShapeArc (from buildings Shapefile) outline description as a field in
the replicated object for a populated building.
-
+ Doesn't increase shapefile size (and impact on replicated object size
should be minimal)
-
+ Would allow for a slight increase in rendering speed, since populated
buildings could be rendered before the shapefile is loaded
-
- Detaches dynamic data from underlying static data. This could present
a problem if we eventually have multiple "layers" of dynamic data, e.g.,
for specific user groups, since it will be more difficult to determine
when data from two different layers is within the same building.
For the first iteration, option (2) seems to be the best approach. We could
also consider a hybrid of (2) and (3), storing both coordinates (for handling
multiple data layers) and an outline (for faster rendering).
As of 010914 the implementation stores both the bounds of the structure
and a reference to the ShapeArc that describes the structure's outline.
-
Class names in the previous version of MOOsburg --
place, landmark, and space -- were bad choices.
All are too vague, landmark doesn't imply "point", there is too
much overlap in the definitions of place and space, and space implies 3D.
Here are some alternatives:
-
spot seems to be a good choice for replace landmark, since
it implies a point (i.e., "the spot where the user is standing").
Spots will, for the most part, likely still be shown as spots on the map, so
the name is also consistent with the UI.
-
region is a generic term for something that you would look at a map
of, and therefore seems like a good replacement for space.
region may, however, not be an ideal choice for things like a
floor of a building.
-
structure generically describes enclosures that may or may not
have multiple floors.
This should be generic enough to handle buildings and ships.
Note that we will need this even if we do not break the set of spots into
an explicit hierarchy, since we will still need metadata for populated
buildings.
A proposed set of classes for managing this data includes:
-
Spot
-
Representation of a single, dimensionless point to which the user can
navigate.
Like the
Landmark class, this would include data
describing coordinates, contents, and view.
-
Structure
-
Representation of 2D structure with one or more "floors".
These have bounds, a floor count, data describing their external shape
(either explicitly or by reference to shapefile data)
and internal layout.
Depending on resolution of the flat-vs-hierarchical issue, these might
also contain a list of pointers to
Region objects
for each floor.
-
Region
-
Container for a set of
Spots and Structures.
Either Region or a helper class would implement the
RenderableSetFactory interface such that for a given
viewpoint a set of Spot and Structure objects
is returned.
Layer management
Management of layers of static data can be handled by the configuration file
scheme described in "Map data configuration" above (or some variant thereof).
In the context of MOOsburg, management of layers of dynamic (content) data
is somewhat more complicated. Such layers might include:
-
A "base layer" containing all defined spots and structures.
Given its probable eventual size, this layer would only be visible at
high level of magnification.
-
A layer that includes at least one spot in each occupied level of
each structure.
This would be visible at all levels of magnification so that somewhere
navigable is visible any time the user peeks into a structure.
a building
-
Layers of "promoted" spots that appear at higher levels of magnification.
This would presumably have to include the structures contained the spots
as well.
Layers of promoted spots might include:
-
Starting places
-
Occupied spots
-
Recently active spots
-
Recently created spots
-
A layer of proposed structure definitions. This would be useful if
we want to allow unlimited creation of spots, but ensure that structure
definitions are more tightly controlled.
-
Personalized layers of spots, e.g.:
-
Bookmarked spots
-
Recently visited spots
-
Spots owned/created by the current user or the user's group
Fundamentally, layers of content data are no different than layers of
static data.
Each layer could be represented by a Region object (parameterized by
magnification thresholds), and
the regions could then simply be added independently to the renderer in
the same way that layers of static data are added.
Duplicate renderable items (spots and structures that appear in multiple layers)
are, however, potentially problematic.
Three possible solutions are:
-
Avoid duplication.
For shared layers (e.g., layers of promoted sites) we could simply ensure
that no spot or structure appears in more than one layer.
This would simplify (elimiate) client-side duplicate handling, but would
not work for personalized layers.
-
Blindly ignore duplication.
Without special handling, the renderer would simply render duplicate
spots on top of each other, with the last rendered representation
"winning".
While this approach does not require computation to detect duplicates,
it does waste cycles rendering items that will simply be overwritten.
This will be relatively cheap for items which are simply rendered by
drawing to a
Graphics object, but will potentially be much
more expensive for items that produce components.
Finally, it is likely that the same item might be renderered differently
depending on which layer it appears in.
At a minimum, this could produce oddities in the display in the upper
renderings of an item do not completely cover the lower ones.
-
Wrap the regions in a "composite" region that merges their data and
filters out duplicates so that, e.g., only the top-most occurrance of
a given renderable item will be visible.
Map/Navigation UI design
Below are a set of general design goals/principles derived from feedback
and experience with the initial MOOsburg interactive map implementation:
-
The map
should support "peeking" inside of structures without changing location.
This is a significant limitation of the current scheme: a user has to
navigate into a building to see what is there.
This is different from the top level map, where everything is browsable
without changing your character's location.
-
The user
should be able to see overview of entire structure (e.g., every floor).
This, along with (1), would ensure that the user has consistent
"random access" navigation to anywhere in the environment.
-
All maps/views should have consistent look-and-feel.
This would primarily mean consistent perspective (birds-eye), but might
also suggest that we want to limit the tools available for constructing
subspace maps to ensure that they look more-or-less like the top-level map.
This represents a trade-off between supporting users (who, particularly
when new to the system, are likely to prefer consistency) and supporting
authors (who are likely to prefer short-cuts like uploading a scanned map).
Supporting more limited subspace maps is also likely to improve
performance, particularly if we want to support the kind of random-access
browsing and navigation implied by (1) and (2).
-
The navigation widget design should
encourage breadth vs. depth by only supporting two levels in the containment
hierarchy and relying on zoom and promotion/filtering/highlighting of
interesting (e.g. occupied) locations to manage detail.
This will:
-
Simplify navigation widgets
-
Simplify visualization features that indicate content and activity within
an obscured space/structure
-
Eliminate problems with inconsistencies between sizes, shapes, and connections
among sub-subspaces.
The top level is defined by the map, and the second level can be constrained
by map data (e.g., building definitions)
This may, however, present scalability and distributability issues.
-
The navigation widget design
should eliminate "default landmark" ("default spot") mess that we have in the
current implementation.
A user should always select the spot that they want to navigate to.
The necessity for a default landmark in the current implementation is
largely a side-effect of having to navigate to a space to browse it.
-
The construction and navigation tools should not rely on contextual
menus as a primary interaction mechanism.
These are in general too obscure, and mouse-button-specific menus cause
addition problems (and/or require special support) on MacOS and other
platforms that do not have a 2+ button mouse.
A UI that met the above goals would support the following
browsing/navigation tasks in MOOsburg:
-
User is outside, browsing for an outside destination.
Basic town-level map is sufficient.
-
User is outside, browsing for a destination inside of a building.
Town-level map with navigable building expansion views needed.
-
User in inside, browsing for outside destination.
View of current floor should remain visible, but town-level map should
be available.
-
User is inside, browsing for a destination on the same floor of the
building they are currently in.
View of current floor is sufficient.
-
User is inside, browsing for a destination inside another building.
Requires same UI support as (2), but view of current floor should remain
visible.
(At least if location not changed, i.e., if the user just browses but doesn't
leave, the map of the current floor should not go away.)
-
User is inside, browsing for a destination on a different floor of the
building they are currently in.
This is a degenerate case of (5) and could be handled with the same UI
elements.
It might, however, be better to provide a shortcut if we believe this
will be a common task.
|