# Triangulation in QGIS

I need to triangulate fire observation bearings from multiple fire towers or points at known locations.

The towers are known points on the map. Fire patrol officers may also provide an observation from a known point. The observer provides a bearing on the fire and a distance estimate. The distance is not that important if I have a bearing from another observer.

I want to draw a line on the bearing from each observation point (obviously the fire towers are fixed points on my map) to ascertain the position of the fire.

The feature I require is to draw the line on the bearing and keep it on the map so I can draw the bearing from the other tower or observer. It would be good if I could then save that for future reference (evidence). How do I do this in QGIS?

• Do you have a table (for example excel) with bearing and observation coordinates? The coordinates are in lat, long?
– Bera
Commented Dec 11, 2023 at 7:32
• Sounds straightforward enough but the details mostly depend on the format of your data. I'd suggest you share a sample. Commented Dec 11, 2023 at 11:36
• This help? gis.stackexchange.com/questions/447021/…
– John
Commented Dec 11, 2023 at 14:16
• Tower 1 is at following coodinate GDA94, MGA Zone 55478639,5276640 Commented Dec 12, 2023 at 0:28
• Tower 2 is at GDA94, MGA Zone 55 496927,5256292 Commented Dec 12, 2023 at 0:29

A stepwise approach to get the coordinates. First I show how to create the lines, and afterwards how to get the coordinates of the points where they cross. To imitate a real-world example, the lines do not cross exactly at the same point.

Final stage: a medium point (probable fire location) with mean coordinates is created, based on all the bearings (black/red dotted lines) from the fire stations (blue points):

And here is your use case with the two coordinates in `EPSG:28355` and bearings you provided; instead of field name distance, I used a reasonable value of 25000 [m] instead. The red dot shows the (probable) location of the fire:

### 1. Create lines from Towers

First, use the following expression to create lines from the fire towers, based on attribute fields `distance` and `bearing`:

``````make_line (
\$geometry,
project (
\$geometry,
distance,
)
)
``````

Here you can see the black line, created with the expression above. The red dotted line is an extended version of the line, using the function `extend()`, to get an intersection with the other lines even if one of the lines is too short:

### 2. Create crossing points

In a second step, create the points where the line from one fire tower crosses the lines of the other fire towers, using this expression:

``````collect_geometries(
array_foreach (
overlay_nearest (
@layer,
extend (
make_line (
\$geometry,
),
0,
1000
),
limit:=9 -- max number of towers to consider
),
intersection (
extend (
make_line (
\$geometry,
),
0,
1000
),
@element
)
)
)
``````

Red points = possible fire locations, created with the expression above:

### 3. Calculate coordinates

Third step: get the coordinates of the intersection points using the following expression. the coordinates are automatically converted from the layer CRS used to WGS84 (lat/lon) coordinates:

``````array_to_string (
array_foreach (
overlay_nearest (
@layer,
extend (
make_line (
\$geometry,
),
0,
1000
),
limit:=10 -- max number of neighboring points to consider
),
with_variable(
'fire',
transform (
intersection (
extend (
make_line (
\$geometry,
),
0,
1000
),
@element
),
@layer_crs,
'EPSG:4326'
),
round (x(@fire),5)  || ';'  ||  round (y(@fire),5)  -- coordinates rounded to 5 decimals
)
)
)
``````

Lat/Lon coordinate values created with the expression:

### 4. Create the point with the mean coordinates

To automatically create the mean coordinates of all the crossing points from each fire tower (and thus the most probable point where the fire is), use this expression:

``````with_variable(
'create_coord',
'
array_mean (
array_agg (
array_mean(
array_foreach (
overlay_nearest (
@layer,
extend (
make_line (
\$geometry,
),
0,
1000
),
limit:=10 -- max number of neighboring points to consider
),
with_variable(
''fire'',
transform (
intersection (
extend (
make_line (
\$geometry,
),
0,
1000
),
@element
),
@layer_crs,
''EPSG:4326''
),
ll(@fire)
)
))))
',
eval(replace (@create_coord,'ll','x'))  || ';'  || eval(replace (@create_coord,'ll','y')))
``````

Creating the point with the mean coordinates of all the intersection points (red dot, expression below) and the coordinate values with the expression above:

To create the red dot with the mean coordinates:

``````with_variable(
'create_coord',
'
array_mean (
array_agg (
array_mean(
array_foreach (
overlay_nearest (
@layer,
extend (
make_line (
\$geometry,
),
0,
1000
),
limit:=10 -- max number of neighboring points to consider
),
with_variable(
''fire'',
transform (
intersection (
extend (
make_line (
\$geometry,
),
0,
1000
),
@element
),
@layer_crs,
''EPSG:4326''
),
latlon(@fire)
)
))))
',
transform (
make_point (
eval(replace (@create_coord,'latlon','x')) ,
eval(replace (@create_coord,'latlon','y'))
),
'EPSG:4326',
@layer_crs
)
)
``````
• Such an impressive answer. Thank you :) Commented Dec 17, 2023 at 8:54