Metacity
  • Welcome
  • Metacity
    • Installation
    • [dev] CGAL Dependency
    • Data Import
    • Models and Attributes
    • Layers
    • Grids
    • Quad-trees
    • Dockerized Processor
    • Development notes
  • Archives
    • DataAPI
      • Development
    • MetacityGL
      • Installation
      • Creating a MetacityGL App
      • Writing Custom Layers
      • Loading Metacity Data
      • Development notes
    • BananaGL
      • Development
    • AMOS
      • Synthetic Population
        • Case Studies
        • Data Specification
        • Activity Chains
        • Spatial Distribution
        • MATSim population input and comparison
        • Households
      • MATSim
        • Basic Info
        • Running Scenario
          • Config File
          • Current state
        • Input information
          • OSM
          • Filtering GTFS
          • Coordinates
        • Output
          • Processing
      • OICT
        • MapResolver
      • Resources
        • Trafic Simulation
        • MATSim
        • Vis and Meta Software
        • Synthetic Population
        • Public Relations
        • Inspiration
    • Metacity Block Edition
      • Epic Games Mega Grant
      • 🧠Internal notes
  • Links
    • Homepage
    • GitHub
  • Code of Conduct
Powered by GitBook
On this page
  • Parsing data
  • Workers
Edit on GitHub
  1. Archives
  2. MetacityGL

Writing Custom Layers

How to display any general data

Each layer's props should extend the MetacityLayerProps interface:

import { MetacityLayerProps } from 'metacitygl';

export function CustomLayer(props: MetacityLayerProps) {
    const { context, onLoaded, enableUI } = props;
    return (
        <div>
            <h1>Custom Layer</h1>
            <p>This is a custom layer</p>
        </div>
    )
}

The returned nodes will get automatically attached to the Metacity UI panel. You can make the UI look however you want.

Each layer gets these props by default:

  • context is a class encapsulating the graphics context, you can use it to modify what gets rendered

  • onLoaded is a callback you must use to signal the application that your layer is ready to display

  • enableUI is a flag that signals you whether the layer UI should get displayed or not

Parsing data

There is a recommended way how to handle any data in MetacityGL. In your custom layer, split the process into 3 parts:

//... other imports
import axios from "axios";
import { Utils } from "metacitygl"

export function CustomLayer(props: MetacityLayerProps) {
    const { context, onLoaded, enableUI } = props;
    
    React.useEffect(() => {
         if (!context)
             return; 
             
         //get your data
         const data = (await axios.get(api)).data as Data;
         
         //parse it using Metacity's Assemblers
         const asm = new Utils.Assemblers.SomeAssembler();
         for (const item in data) {
             //pass the item to the assembler
         }
         if (asm.empty)
             return;
         
         const buffers = asm.toBuffers();
         //transform it into a Model
         const model = Graphics.Models.SomeModel.create(buffers);
         //pass it to context
         context.add(model);
        
    }, [context]);
    
    return (...)
}
  1. Transforming the data into a renderable model can be tricky. MetacityGL provides built-in tools called Assemblers that can make your life a little easier. The Assemblers allow you to parse the data incrementally. When you are done, you can export the data from the Assembler in a form that can be directly passed into one of Metacity's Models.

  2. Pass the created model into the graphics context.

Workers

The data-parsing steps usually require some number-crunching. It is best to isolate these steps into a separate worker process and pass the result back to the layer component.

dataWorker.ts
import axios from "axios";
import { Utils } from "metacitygl"

declare var self: any;

interface Data {
    //TODO
}

self.onmessage = async function (e: any) {
    const { api, ... } = e.data;
    const data = (await axios.get(api)).data as Data;

    const asm = new Utils.Assemblers.SomeAssembler();
    for (const item in data) {
        //pass the item to the assembler
    }
    
    if (!asm.empty) {
        const buffers = asm.toBuffers();
        const transferables = asm.pickTransferables(buffers);
        self.postMessage(buffers, transferables);
    }
}

With this worker, you can structure the layer the following way:

import Worker from "./dataWorker?worker&inline";
import { Graphics } from "metacitygl"

export function CustomLayer(props: MetacityLayerProps) {
    const { context, onLoaded, enableUI } = props;
    
    React.useEffect(() => {
        if (!context)
             return; 
        
        // instantiate a worker     
        const worker = new Worker();
        
        //start a job
        worker.postMessage({
           api: "https://my.api"
        });
        
        //process the job result
        worker.onmessage = (e) => {
            worker.terminate();
            const model = Graphics.Models.SomeModel.create(e.data);
            context.add(model);
        };  
    }, [context]);
    
    return (...)
}

There is much more you could do:

  • store the reference to the Model in the layer and allow modifying it with the UI

  • you could create a pool of workers and reuse them between layers instead of creating and terminating them for better performance, etc.

See the other pages for a better grasp of Models, Assemblers, and the context.

PreviousCreating a MetacityGL AppNextLoading Metacity Data

Last updated 1 year ago

Getting your data is probably the easiest part. Use a library you like (e.g. ?) and download it.

Create a Model - you can create a completely new one using or reuse one defined in the library.

axios
three.js