Skip to content
getgeolens.com

Analysis

The Analysis panel runs PostGIS geometry operations against the layers already in your map. Open a map in the Map Builder, then click Analysis in the right-hand rail.

There are eight operations: buffer, centroid, clip, dissolve, spatial join, measure, select by location, and intersect. All but dissolve can draw a preview on the map before you commit to anything. All eight can write their result to a new dataset in your catalog.

The Layer dropdown lists the vector layers currently on the map. A layer qualifies when the dataset behind it is vector and has a known geometry type, which leaves out raster layers, VRT mosaics, and DEMs. If the panel tells you to add a dataset layer, the map has no vector layer on it yet.

Analysis reads the dataset behind the layer, not the layer as you see it. A CQL2 filter that hides features on screen does not exclude them from the operation, and neither does the eye icon. To analyze a subset, save that subset as its own dataset first.

Preview runs the operation and returns the first 500 features as a temporary overlay. Nothing is written to the catalog. When the result is cut off at 500, a notice reports the source total so you can see how much the preview leaves out. Clear preview removes the overlay, and so does leaving the map.

Create dataset queues the same operation over every feature and registers the output as a new private dataset you own. It needs the upload and export permissions, so the New dataset name section stays hidden for accounts missing either one. The new dataset counts against your dataset quota.

Dissolve is an aggregate rather than a per-feature transform, so it has no preview shape. Its only button is Create dataset.

Buffer grows each feature by a fixed distance and returns the resulting polygon. Enter the distance in meters, kilometers, feet, or miles, and the panel converts it before sending. The ceiling is 100 km.

Buffering is geodesic. GeoLens casts the geometry to geography first, so 500 meters means 500 meters on the ground whether the feature sits on the equator or in northern Norway. A buffer computed in degrees would come out distorted at high latitude, because a degree of longitude covers less ground the further you get from the equator.

Centroid replaces each feature with a single point at its center of mass, one point per input feature.

The center of mass of a concave shape can fall outside the shape. The centroid of a horseshoe-shaped parcel lands in the gap. This is the ordinary ST_Centroid definition rather than a guaranteed-inside point, which matters if you plan to join the output back to whatever contains it.

Clip keeps the parts of each feature that fall inside a mask. There are two ways to supply the mask.

Draw clip area puts the map into polygon-drawing mode. Click to place vertices, double-click to finish. The polygon stays on screen afterwards so you can see what you are about to clip against. Drawing needs a pointer.

Or clip to a layer takes the mask from another polygon layer already on the map, and combines every polygon in it into a single mask. Use this when the mask is real data rather than a sketch, or when you are working without a mouse.

Clipped output keeps the dimension of its source: clipping polygons gives you polygons, clipping lines gives you lines. Features that only graze the mask boundary meet it at a lower dimension, and those are dropped rather than returned as stray fragments.

Dissolve merges features into one geometry. With no group field, the whole layer collapses into a single row. Pick a Group by field and you get one row per distinct value, so dissolving parcels by zoning returns one multipolygon per zoning class.

Dissolve output carries the group column and a generated source_count, the number of input features behind that row. Every other attribute is dropped, since there is no correct answer for the owner of 4,000 merged parcels.

Spatial join transfers columns from a second layer without changing the source geometry. Pick a Join layer, then choose up to 10 fields to transfer; each one lands on the output as join_<name>. Every source feature also gets a generated join_count column, the number of join-layer features whose geometry intersects it.

Unlike clip or select by location, nothing is filtered or cut: every source feature survives the join, whether it matched zero join-layer features or several.

When a source feature matches more than one join-layer feature, the transferred join_<name> values come from exactly one of them — the match with the lowest join-layer feature ID — not an aggregate across all matches. join_count still reports the true number matched, so a value greater than 1 is the signal that the transferred fields represent only one of several matches.

Measure adds two computed columns to every feature: area_sqm and length_m. Both are emitted for every feature regardless of geometry type, since a layer typed as polygons can still hold a stray line row — ST_Area of a line is 0 and ST_Length of a polygon is 0, so a mixed layer measures correctly throughout rather than silently picking one column to trust.

Measurement is geodesic, the same geography cast buffer uses, so area and length come out correct on the ground rather than distorted by latitude.

Select by location keeps whole source features that intersect a mask, drawn or from another polygon layer — the same Draw clip area and Or clip to a layer controls clip uses. The difference is what happens to the geometry: clip cuts each feature down to the part inside the mask, while select by location keeps a matching feature exactly as it is, or drops it entirely if it does not intersect.

Intersect computes the pairwise overlay between the source and a mask layer and writes one output feature per overlapping pair, carrying attributes from both sides. It only takes its mask from Or clip to a layer — there is no drawn-polygon option, since a drawn area does not have attributes of its own to carry through.

Buffer, centroid, clip, spatial join, measure, and select by location all copy every attribute column from the source to the output, so the saved dataset still joins back to the original on whatever key it already had; spatial join and measure add their generated columns alongside those. Intersect carries attributes from both the source and the mask layer. Dissolve is the exception described above.

The output is an ordinary vector dataset. Style it in the builder, export it in the same formats as anything else in the catalog, and serve it through the OGC API endpoints. It starts private, and you change that from the dataset’s Access tab.

GeoLens drops rows that produced nothing before it registers the dataset, so an operation over a layer with some empty geometries saves fewer rows than the source has. If an operation produces no features at all, the job fails rather than registering an empty dataset.

The panel shows a status line while the job runs. A queued job says so and names what it is waiting for, then the line moves through Creating dataset… and Saving the dataset… to Dataset created, which arrives with an Add to map button next to it.

Analysis is deliberately queued below interactive uploads, so on a busy instance a job can sit at Queued for a while. That is the queue working as intended: the job is waiting for a free worker.

You can run one analysis job at a time. Create dataset stays disabled while one is in flight, and the API answers a second request with a 429. The result still reports if you close the panel or navigate away while it runs.

Administrators can see what any job was asked to do. Every analysis run records its parameters against the job row, and Admin → Jobs shows them: the operation, the source dataset, the output title you typed, and whichever of buffer distance, dissolve group field, clip/select-by-location/intersect mask source, and spatial join layer and fields applies. This is what makes a failed run diagnosable, since analysis-buffer failed on its own says very little. A mask you drew on the map is recorded only as having been drawn — the polygon itself is not stored, because it can run to kilobytes.

| Limit | Value | | --- | --- | | Buffer distance | 100 km | | Preview result | 500 features | | Drawn clip area | 5,000 vertices | | Mask layer (clip, select by location, intersect) | 1,000 features | | Join fields transferred, spatial join | 10 | | Source features, dissolve | 250,000 | | Source features, spatial join | 250,000 | | Source features, select by location | 250,000 | | Source features, intersect | 100,000 | | Source features, buffer | 500,000 | | Source features, measure | 1,000,000 | | Output dataset size | 2 GB | | Analysis jobs per user | 1 at a time |

Centroid and clip carry no source-feature ceiling, because neither can produce more data than it consumes — clip’s mask layer is what gets bounded instead. Buffer and intersect are capped because they can: buffer inflates every geometry it touches, and intersect can emit more than one output row per source feature when it overlaps several mask features. Dissolve, spatial join, select by location, and measure are capped for query cost rather than output growth: dissolve holds union state in memory that grows with the input, spatial join and select by location each probe a second table once per source row, and measure casts every row to geography before it can measure it.

The distance, mask, and source-feature limits are checked before the job is queued, so you get an immediate error naming the limit you hit. Output size is the exception, since nothing can measure the result until it exists. That one fails the job partway through and drops the partial table.

If your administrator has enabled AI features, you can ask the chat for a buffer, a centroid, or a clip in plain language: “buffer the schools by 500 meters”, “show the center point of each parcel”, or “clip roads to the city boundary”. The answer arrives as the same temporary overlay the Preview button produces.

Chat handles buffer, centroid, and clip against another layer — chat cannot draw a mask, so a clip request needs a polygon layer already on the map. Spatial join, measure, select by location, and intersect are not available in chat: they are simply not part of the chat tool’s operation set, not because chat lacks a way to collect their parameters — select by location and intersect take a second layer the same way clip does. Dissolve has nothing to preview regardless. While a chat preview sits on the map, its badge offers Save as dataset…, which opens the Analysis panel with the operation and distance already filled in.

Two endpoints back the panel:

POST /api/datasets/{dataset_id}/analysis/preview/
POST /api/datasets/{dataset_id}/analysis/materialize/

preview is synchronous and returns a GeoJSON FeatureCollection under the same 500-feature cap. materialize returns a job id. Poll GET /api/jobs/{job_id} until the status reads complete, then take dataset_id off the response.

Both require an authenticated user with read access to the source dataset; an anonymous request returns 401 even when the dataset is public. materialize also requires the upload and export permissions: it creates a dataset, and that dataset carries the source’s attributes, so it is gated like a download as well as like an upload. A role holding only one of the two gets a 403. Request and response schemas live in the API reference.