Skip to content

Chapter 2: Building Data API Client#

Welcome back! In Chapter 1: Data Types & Models, we learned about the blueprints (data types) that define the structure of information in our building-height application. We saw how we expect geographic shapes to look (like Coords and FileContents) and what details we might get about gallery images (like GalleryImage).

Knowing what the data looks like is great, but how do we actually get that data into our application? Especially the complex building geometry information?

Getting Information from Afar: The Need for an API Client#

Imagine our application is like a detective trying to understand a specific building. The blueprints from Chapter 1 tell the detective what kind of information to look for (the building's shape, height, location details, maybe photos), but the information itself isn't just sitting inside the application.

Most likely, this detailed building data lives somewhere else – on a powerful server managed by a company that specializes in collecting and organizing geographic information. To get the data we need, our application has to ask that server for it.

This is where the Building Data API Client comes in.

Think of it as a specialized messenger or assistant. When our application needs information about a building at a specific location (say, determined by the user clicking on a map or providing coordinates), this assistant is given the task:

  • "Go to the 'Building Information Library' (the external API service)."
  • "Look up the details for the building located at these specific coordinates (latitude and longitude)."
  • "Also, consider that we're viewing it from a certain direction (camera direction)."
  • "Please bring back the architectural plans (building geometry/GeoJSON) and any relevant photo details (camera position/orientation)."

The Building Data API Client is the piece of code that handles this request and retrieval process.

The Core Task: Fetching Building Data#

The main job of our Building Data API Client is to get building geometry and camera information based on location and view direction.

Here's the core function in our project that performs this task:

// A simplified look at src/api/fetch-building.ts
const API_URL = "https://api.buildingshistory.co.uk";

export const fetchBuilding = async (
  lat: string, // Latitude coordinate
  lon: string, // Longitude coordinate
  camAltitude: string, // Altitude of the camera
  camDirection: string // Direction the camera is facing
) => {
  // ... code to prepare the request URL ...

  // Send the request and get the response
  const response = await fetch(/* ... constructed URL ... */);

  // Convert the response from text into a usable structure
  const data = await response.json();

  // ... code to check if data is valid and extract relevant parts ...

  // Return the extracted data or null if not found
  return {
    geojson: data.data.building_part[0].geojson,
    cameraGPSData: [ /* ... extracted camera details ... */ ],
  };
  // OR return null; if no building is found
};

This fetchBuilding function is our primary interface to the external building data API. You give it the location and viewing details, and it promises to go get the data for you (that's what async and await help with – they manage the "waiting" for the internet request to finish).

How to Use fetchBuilding#

Using this function is straightforward. You call it with the required geographic and camera information:

import { fetchBuilding } from "./api/fetch-building"; // Assuming you're in a file that can import it

async function getBuildingData() {
  const latitude = "51.5074"; // Example London coordinates
  const longitude = "0.1278";
  const altitude = "50"; // Example camera altitude
  const direction = "90"; // Example camera direction (East)

  console.log("Asking the API client for building data...");

  const buildingInfo = await fetchBuilding(
    latitude,
    longitude,
    altitude,
    direction
  );

  if (buildingInfo) {
    console.log("Successfully fetched building data!");
    console.log("GeoJSON shape received:", buildingInfo.geojson);
    console.log("Camera position received:", buildingInfo.cameraGPSData);
    // Now you can use buildingInfo.geojson and buildingInfo.cameraGPSData
    // in other parts of the application, like for rendering or display.
  } else {
    console.log("No building found at this location.");
  }
}

// Call the async function to start the process
getBuildingData();

When you run code like this, the fetchBuilding function sends a request over the internet to the API service. Once the service responds, fetchBuilding processes that response and gives you back an object containing:

  • geojson: The geometric shape data for the building, following the general idea of the geographic data types we saw in Chapter 1: Data Types & Models.
  • cameraGPSData: Information about the camera's location and direction, which is crucial for knowing how to view the building in 3D space later.

If the API service doesn't find a building at those exact coordinates, fetchBuilding will return null.

Under the Hood: How the API Client Works#

Let's peek inside the fetchBuilding function (src/api/fetch-building.ts) to understand the steps it takes.

The Process (Non-Code Walkthrough)#

Here's the sequence of events when fetchBuilding is called:

  1. Preparation: The function takes the input latitude, longitude, camera altitude, and camera direction. It might do some minor adjustments (like ensuring the longitude is negative, as required by this specific API).
  2. Constructing the Request: It builds a specific web address (a URL) for the API service. This URL includes the location and direction parameters. It's like writing the exact address and specific request on a letter.
  3. Sending the Request: It uses a built-in web feature (the fetch function) to send a request over the internet to the API URL it just built.
  4. Waiting for Response: The function pauses (await) and waits for the API service to send back a response.
  5. Receiving Data: When the response arrives, it's raw text. The function converts this text into a structured format that JavaScript can easily work with (usually a JSON object).
  6. Checking the Data: It looks at the received JSON data to see if it contains the building information we need (specifically, if it found a building and if that building has GeoJSON data).
  7. Extracting and Formatting: If the data is found and looks valid, it pulls out the GeoJSON part and the camera information. It packages this information into a neat object.
  8. Returning the Result: It returns the packaged data object or null if no valid building data was found.

Visualizing the Interaction#

Here's a simple diagram showing this flow:

sequenceDiagram
    participant UI as User Interface
    participant FC as fetchBuilding Client
    participant API as External API Service

    UI->>FC: Call fetchBuilding(lat, lon, alt, dir)
    FC->>API: Construct API URL and Send Request (GET)
    API-->>FC: Send Response (JSON data)
    FC->>FC: Process JSON data
    FC->>FC: Check for building/geojson
    alt Building data found
        FC->>FC: Extract geojson and camera info
        FC-->>UI: Return { geojson, cameraGPSData }
    else No building data
        FC-->>UI: Return null
    end

Code Details#

Let's look at specific parts of the src/api/fetch-building.ts code:

Building the URL:

// src/api/fetch-building.ts (simplified)
const API_URL = "https://api.buildingshistory.co.uk";

export const fetchBuilding = async (
  lat: string, lon: string, camAltitude: string, camDirection: string
) => {
  // Ensure longitude is negative for this specific API requirement
  let lng = parseFloat(lon);
  if (lng > 0) lng = -Math.abs(parseFloat(lon));

  // Construct the full request URL with parameters
  const url = `${API_URL}/api/v1/building-part/nearest?latitude=${parseFloat(lat)}&longitude=${lng}&imagedirection=${camDirection}`;

  // ... rest of the function ...
};

This part takes the input strings, converts latitude and the potentially adjusted longitude to numbers, and then combines the base API URL (API_URL) with the specific endpoint (/api/v1/building-part/nearest) and the parameters (?latitude=...&longitude=...&imagedirection=...). This creates the exact web address needed for the request.

Sending the Request and Getting JSON:

// src/api/fetch-building.ts (continued)
// ... URL construction ...

  // Use the 'fetch' API to send the request
  const response = await fetch(url);

  // Wait for the response and parse it as JSON
  const data = await response.json();

  // ... rest of the function ...
};

The await fetch(url) line is where the code contacts the external server and waits for a reply. The await response.json() line then takes the reply (which is in a text format called JSON) and turns it into a JavaScript object that our code can easily work with, like accessing properties using dots (data.data.building_part).

Checking and Returning Data:

// src/api/fetch-building.ts (continued)
// ... fetch and json parsing ...

  // Check if the response has the structure we expect and contains geojson
  if (
    data.data.building_part.length > 0 &&
    data.data.building_part[0].geojson
  ) {
    // If valid data is found, extract and return it
    return {
      // Extract the geojson part
      geojson: data.data.building_part[0].geojson,
      // Format and extract camera details from the original inputs
      cameraGPSData: [
        {
          coordinates: [lng, parseFloat(lat), parseFloat(camAltitude)],
          bearing: parseFloat(camDirection),
          altitude: parseFloat(camAltitude),
        },
      ],
    };
  }

  // If no valid building data was found, alert the user and return null
  alert("No records found in our database"); // User-friendly message
  return null;
};

This final part checks the structure of the received data object (data.data.building_part.length > 0 && data.data.building_part[0].geojson). If these checks pass, it means we got useful building information. It then creates and returns an object containing the geojson data and the formatted cameraGPSData. If the checks fail (e.g., no building found), it shows a message to the user and returns null.

Connecting to Chapter 1#

Notice how the geojson data returned by fetchBuilding is expected to contain information like type and coordinates in a structure similar to the FileContents blueprint we saw in Chapter 1: Data Types & Models. Although fetchBuilding doesn't explicitly return a FileContents type, the data itself is GeoJSON, which follows that structure. Similarly, the cameraGPSData array contains objects with coordinates, bearing, and altitude, fitting the kind of location-aware data structures needed later in the pipeline. The API client's job is to fetch data that matches these expected blueprints.

Conclusion#

In this chapter, we explored the Building Data API Client. We learned that its purpose is to act as our application's messenger, fetching specific building geometry and camera information from an external web service (an API) based on location and view direction. We saw the main fetchBuilding function, how to use it, and got a look under the hood at how it constructs requests, communicates with the API service over the internet, processes the response (turning it into usable data), and returns the necessary information (or indicates if nothing was found). This retrieved data, especially the GeoJSON, follows the structural patterns we discussed in Chapter 1: Data Types & Models.

Now that we can get geographic data like building shapes and camera positions, we'll need tools to manipulate and work with these geographic coordinates. That's exactly what we'll cover in the next chapter!

Next Chapter: Geographic Utility Functions


Generated by AI Codebase Knowledge Builder