Back

Geophysics Functions

Overview

The geophysics module provides functions for satellite-based geodetic analysis, specifically for processing InSAR (Interferometric Synthetic Aperture Radar) data. These functions allow projecting 3D displacement fields onto a line-of-sight (LOS) direction and converting projected displacements into interferometric fringe patterns.

InSAR Projection

insar Function

// Project a 3D displacement field onto a satellite line-of-sight (LOS) direction.
// Returns the scalar projection (dot product) of each displacement vector
// onto the unit LOS vector.
Serie<double> insar(
    const Serie<Vector3D> &displacements,  // 3D displacement vectors
    const Vector3D        &los              // Line-of-sight unit vector
);

The insar function computes the component of each 3D displacement vector along the satellite's line-of-sight direction. This simulates what an InSAR satellite would measure: the range change between the satellite and the ground surface. The LOS vector should be a unit vector pointing from the ground toward the satellite.

InSAR Example

// Simulated 3D displacement field from a fault model
df::Serie<Vector3D> displacements{
    {0.01, 0.02, -0.005},
    {0.03, 0.01, -0.010},
    {0.02, 0.03, -0.008},
    {0.005, 0.005, -0.002}
};

// Satellite LOS direction (e.g., descending orbit, ~23 deg incidence)
// Typically: LOS = {east, north, up} components
Vector3D los = {-0.38, -0.09, 0.92};  // Approximate descending LOS

// Project displacements onto LOS
auto los_disp = df::geo::insar(displacements, los);
// los_disp contains the scalar range change at each point

for (size_t i = 0; i < los_disp.size(); ++i) {
    std::cout << "Point " << i << ": LOS displacement = "
              << los_disp[i] * 1000.0 << " mm" << std::endl;
}

Interferometric Fringes

fringes Function

// Convert scalar displacement values to interferometric fringe pattern.
// Each fringe cycle represents one full wavelength of displacement.
Serie<double> fringes(
    const Serie<double> &los_displacements,  // LOS displacement values
    double fringeSpacing                       // Fringe spacing (e.g., half-wavelength)
);

The fringes function wraps displacement values into a periodic fringe pattern, simulating the wrapped phase that an InSAR interferogram displays. The fringeSpacing parameter determines the displacement interval per fringe cycle. For C-band SAR (e.g., Sentinel-1), one fringe corresponds to about 2.8 cm of LOS displacement (half the radar wavelength of ~5.6 cm).

Fringes Example

// LOS displacements from the insar() function
auto los_disp = df::geo::insar(displacements, los);

// Convert to fringes with C-band half-wavelength spacing (2.8 cm)
double half_wavelength = 0.028;  // 28 mm
auto fringe_pattern = df::geo::fringes(los_disp, half_wavelength);

// fringe_pattern values are in [0, 1) representing the wrapped phase
// 0 and 1 correspond to the same fringe color

Complete Example

InSAR Processing Pipeline

#include <dataframe/Serie.h>
#include <dataframe/geo/geophysics.h>
#include <dataframe/geo/grid/from_dims.h>
#include <dataframe/geo/interpolation/idw.h>
#include <iostream>

int main() {
    // Model displacement field at scattered points
    df::Serie<Vector<3>> model_pts = /* fault model observation points */;
    df::Serie<Vector3D>  model_disp = /* 3D displacements from BEM model */;

    // Create a regular grid for visualization
    auto grid_pts = df::grid::cartesian::from_dims<3>(
        {100, 100, 1},
        {0.0, 0.0, 0.0},
        {50000.0, 50000.0, 0.0}  // 50 km x 50 km surface grid
    );

    // Interpolate displacements to the grid
    auto grid_disp = df::geo::idw<Vector3D, 3>(
        model_pts, model_disp, grid_pts
    );

    // Project onto ascending orbit LOS
    Vector3D los_asc = {0.38, -0.09, 0.92};
    auto los_asc_disp = df::geo::insar(grid_disp, los_asc);

    // Project onto descending orbit LOS
    Vector3D los_desc = {-0.38, -0.09, 0.92};
    auto los_desc_disp = df::geo::insar(grid_disp, los_desc);

    // Generate fringe patterns (C-band)
    auto fringes_asc  = df::geo::fringes(los_asc_disp, 0.028);
    auto fringes_desc = df::geo::fringes(los_desc_disp, 0.028);

    std::cout << "Generated " << fringes_asc.size()
              << " fringe values for ascending and descending orbits\n";

    return 0;
}