Week 9: Ripley’s K Worked Example

From a GIScience question to an interactive MVC application · 15.06.2026

Materials

Download Week 9 Slides (PDF) →
Download the complete Week 9 Java project (ZIP) →

Learning Goals

This week brings the course ideas together in one complete example. By the end, you should be able to:

1. From a Spatial Question to a Measurement

The question: are the events in a study area more clustered or more dispersed than we would expect from a random pattern?

The events could be trees, disease cases, shops, crimes, or traffic accidents. Their meanings differ, but the program receives the same abstraction: a list of (x, y) coordinates inside a study window.

Ripley’s K starts with a simple operation: choose an event, draw a circle of radius d, and count the other events inside it. Repeat this for every event and for several radii. The important question is therefore not simply “is the pattern clustered?”, but “at which distances is it clustered or dispersed?”

Observed result Interpretation at distance d
More neighbours than under CSR Clustered
Similar neighbour counts to CSR Consistent with CSR
Fewer neighbours than under CSR Dispersed

K and the easier-to-read L transformation

Under theoretical CSR, the expected value is K(d) = pi * d^2. Because K naturally grows as the radius grows, we also calculate:

L(d) - d = sqrt(K(d) / pi) - d

This transformation moves the theoretical random reference to zero: values above zero suggest clustering, values below zero suggest dispersion, and values near zero suggest a pattern close to CSR. The simulation envelope gives the stronger comparison used by the application.

2. Randomness, Envelopes and Edges

Monte Carlo simulation

One random pattern can be unusual by chance, so the program generates 199 CSR patterns. Each simulation uses the same number of events and the same 800 × 600 study window as the observed pattern. At each radius, the central 95% of simulated K values forms a pointwise simulation envelope.

Translation edge correction

An event near the boundary has less observable space around it: some possible neighbours would lie outside the study window. The implementation compensates for this using the overlap between the window and a translated copy of itself.

overlapArea = (width - abs(dx)) * (height - abs(dy))
edgeWeight  = studyArea / overlapArea

Pairs with less observable overlap receive a larger weight. This corrects a measurement problem; it does not invent points outside the window.

3. The Interactive Application

Code/Week9/
|-- src/at/ac/univie/gis/week9/ripleyk/
|   |-- model/
|   |   |-- EventPoint.java       one coordinate pair
|   |   |-- RipleyKModel.java     events, K estimator and simulations
|   |   `-- RipleyKResult.java    one result row and its interpretation
|   |-- view/
|   |   `-- RipleyKView.java      draws events and scan circles
|   `-- controller/
|       `-- RipleyKController.java  input, analysis and result table
`-- test/
    `-- RipleyKModelCheck.java     repeatable numerical checks

Run: at.ac.univie.gis.week9.ripleyk.controller.RipleyKController.

Click in the white study area to create a point pattern, then select Compute K. The pattern is frozen, scan circles are shown, and a result table reports radii 25, 50, 75, and 100 pixels.

Model: geometry without GUI dependencies

EventPoint deliberately does not use java.awt.Point. The model represents spatial data and performs the analysis without depending on Swing or AWT, so the numerical logic can be tested independently.

public class EventPoint {
    private final double x;
    private final double y;

    public EventPoint(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double distanceTo(EventPoint other) {
        double dx = x - other.x;
        double dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Controller: listen, update, repaint

The controller repeats the interaction cycle from Weeks 7 and 8. It receives a mouse event, updates the model, and asks the view to redraw. Once analysis starts, the point pattern is frozen so the displayed results still match the data.

view.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseReleased(MouseEvent e) {
        if (model.isAnalysisMode()) {
            status.setText("The pattern is frozen in analysis mode.");
            return;
        }

        model.addEvent(e.getX(), e.getY());
        view.repaint();
    }
});

Core estimator: formula becomes loops and conditions

The mathematical notation becomes an ordered-pair loop. For each pair, the model calculates an edge weight and one distance, then checks that distance against every radius.

for (int i = 0; i < n; i++) {
    EventPoint first = points.get(i);

    for (int j = 0; j < n; j++) {
        if (i == j) {
            continue;
        }

        EventPoint second = points.get(j);
        double dx = Math.abs(first.getX() - second.getX());
        double dy = Math.abs(first.getY() - second.getY());
        double overlapArea = (width - dx) * (height - dy);
        double edgeWeight = area / overlapArea;
        double distance = first.distanceTo(second);

        for (int r = 0; r < radii.length; r++) {
            if (distance <= radii[r]) {
                weightedCounts[r] += edgeWeight;
            }
        }
    }
}

After counting, each radius is normalised by the study area and the number of ordered event pairs:

K[d] = area * weightedCounts[d] / (n * (n - 1))

Monte Carlo: a loop around the same estimator

The random reference does not require a second K algorithm. The model generates CSR point sets and calls the same computeK() method used for the observed events.

for (int simulation = 0;
     simulation < simulationCount;
     simulation++) {

    List<EventPoint> randomEvents = new ArrayList<>();
    for (int i = 0; i < events.size(); i++) {
        randomEvents.add(new EventPoint(
                random.nextDouble() * width,
                random.nextDouble() * height));
    }

    double[] simulatedK = computeK(randomEvents, width, height);
    // Store one simulated value for each radius.
}

Result object: data and interpretation stay together

Each RipleyKResult represents one row in the table. It stores the radius, observed and expected K, L(d)-d, and both envelope limits. Its interpretation rule is explicit and reusable:

public String getInterpretation() {
    if (observedK > upperEnvelope) {
        return "Clustered";
    }
    if (observedK < lowerEnvelope) {
        return "Dispersed";
    }
    return "Consistent with CSR";
}

4. How to Read the Result Table

Column Meaning
Radius d The distance scale currently being analysed.
Observed K The edge-corrected estimate for the points you clicked.
CSR pi*d^2 The theoretical K value under complete spatial randomness.
L(d)-d A transformed value whose theoretical CSR reference is zero.
95% lower / upper The pointwise envelope from the 199 simulated CSR patterns.
Interpretation Clustered, dispersed, or consistent with CSR at this radius.

Interpret one radius at a time. A point pattern can be clustered at short distances, consistent with CSR at medium distances, and dispersed at longer distances. Avoid assigning one global label unless the result is stable across the full distance range.

The demo measures distance in pixels. Real GIS analyses should use an appropriate projected coordinate reference system with meaningful distance units, not raw longitude and latitude.

5. The Complete Modelling Cycle

  1. Phenomenon: events occur in a bounded study area.
  2. Question: does their arrangement differ from spatial randomness?
  3. Conceptual model: events, distances, neighbours, scale, boundaries, and a random reference.
  4. Object model: EventPoint, RipleyKModel, RipleyKResult, view, and controller.
  5. Algorithm: pair loops, distance tests, edge weights, normalisation, simulation, and percentiles.
  6. Interface: draw a pattern, compute K, and interpret one table row per radius.

This is the central lesson of the worked example: a GIScience method becomes software by making its concepts, responsibilities, state changes, and calculations explicit.