Showing antenna symbols on the map: point symbols or features (polygons)

If you want to use symbology only, I propose a solution inspired by my answer from a similar question: Creating sector lights in QGIS?.


Following a similar approach, and assuming you are working on a Projected CRS (instead, if you are using a Geographic Coordinate System, see the note at the end of the answer), I want to underline that I will focus the attention on the explanation of the minimal things to do for reproducing the desired result: this means that some other minor parameters (like sizes, widths and so on) should be easily adjusted by you for better fitting your needs.

Furthermore, I assume that "AZIMUTH" is the field which stores the azimuth values and "BEAMWIDTH" is the field which stores the antenna beam widths.

Solution

We will render the points with a Single symbol and by recurring to one Simple Marker and two Geometry generator symbol layers:

enter image description here

In the further explanation, I will follow the same order of the symbols in the image above.

1) Simple Marker

I chose a default symbol of a red circle (this is the easier part of this tutorial), having a size of 3 mm and a width of 0.4 mm.

2) Geometry Generator No. 1

Add a new symbol layer and select the Geometry generator and the LineString / MultiLineString types:

enter image description here

Insert this expression in the Expression field:

make_line(
 $geometry,
 make_point($x + 300*cos(radians(90 -  "AZIMUTH" )), $y + 300*sin(radians((90 - "AZIMUTH" ))))
)

We have just defined the arrow which points towards the azimuth set (for creating the arrow, remember to select the Arrow symbol layer type under the Line option from the main symbol Menu). Please note that 300 represents a distance in meters and it's an arbitrary value, so feel free to change it according to your needs.

3) Geometry Generator No. 2

Add a new symbol layer and select the Geometry generator type and the Polygon / MultiPolygon types:

enter image description here

Insert this expression in the Expression field:

CASE
WHEN ("BEAMWIDTH") <= 180
THEN
intersection(
  buffer(
   $geometry, 200),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 -  "AZIMUTH" - "BEAMWIDTH"/2 )), $y + 2000*sin(radians((90 - "AZIMUTH" - "BEAMWIDTH"/2 )))),
      make_point($x + 2000*cos(radians(90 -  "AZIMUTH" )), $y + 2000*sin(radians((90 - "AZIMUTH" )))),
      make_point($x + 2000*cos(radians(90 - "AZIMUTH" + "BEAMWIDTH" /2)), $y + 2000*sin(radians((90 - "AZIMUTH" + "BEAMWIDTH"/2)))),
      $geometry)
     )
    )
   )
  )

WHEN ("BEAMWIDTH") > 180
THEN
difference(
  buffer(
   $geometry, 200),
   make_polygon(
    geom_from_wkt(
     geom_to_wkt(
      make_line(
       $geometry,
       make_point($x + 2000*cos(radians(90 -  "AZIMUTH" - "BEAMWIDTH"/2 )), $y + 2000*sin(radians((90 - "AZIMUTH" - "BEAMWIDTH"/2 )))),
       make_point($x - 2000*cos(radians(90 -  "AZIMUTH" )), $y - 2000*sin(radians((90 - "AZIMUTH" )))),
       make_point($x + 2000*cos(radians(90 - "AZIMUTH" + "BEAMWIDTH" /2)), $y + 2000*sin(radians((90 - "AZIMUTH" + "BEAMWIDTH"/2)))),
       $geometry)
      )
     )
    )
   )

END

We have just defined the sector. Please note that 200 and 2000 represent distances in meters and they are arbitrary values because I'm trying to create a polygon to intersect with the circle having a radius of 200 m, so feel free to change them according to your needs.

Final result

If you correctly perform the previous tasks, you should be able to get results like these ones (the labels are added apart from this solution and they should only explain better the context):

enter image description here

Note

If you are using a Geographic Coordinate System, i.e. if you are dealing with degrees and not with distances, it should be enough using the proper values when I used a distance in the previous formulas. The distances I used are:

  • 300 m (see Geometry Generator No. 1);
  • 200 m (see Geometry Generator No. 2);
  • 2000 m (see Geometry Generator No. 2);

so you may replace it with other arbitrary values expressed in degrees (for example, 0.0002, 0.002 and so on).

Bonus

I have attached the style here: you may open this code with any text editor and save it as a QGIS Layer Style file (i.e. with a .qml extension).

The above style was created using QGIS 2.18.4 (it must have the same name of the shapefile you are using).


A few days ago a new plugin was added to QGIS called Wedge Buffer Processing Algorithm. This looks as if it might be of interest.

As the name suggests it's a processing algorithm, so you'll need to run it from the processing toolbox. Not had a chance to try it yet though.

It creates sectors of circles - like a normal circular buffer, but the wedge angle and radius can be set using field values.

Documentation and screenshots can be seen on the github page


Big kudos to mgri.

In our test layer, everything worked smoothly. In a production layer, after two/three hours, I managed to track down an issue with $geometry. Had been exporting a point layer from a platform, didn't take notice, but it was MultiPoint. This seemed to cause issues: the arrow wasn't drawn; and strangely enough only the calculated points made the polygon of the circles.

Another thing is I'm using a variable radius. (not sure if it's the right word in this case, you could also name it 'beam length' or whatever).

Here's what I'm using now, with a MultiPoints geometry type layer (while in fact all features are a single point), and it works for me in QGis 2.18.3

Arrow expression No arrow if 360°.

CASE

WHEN ("BEAMWIDTH") = 360
THEN 
make_line(
 make_point($x, $y),
 make_point($x + "RADIUS"*cos(radians(90 -  "AZIMUTH" )), $y + "RADIUS"*sin(radians((90 - "AZIMUTH" ))))
)

END

Polygon expression

CASE

WHEN ("BEAMWIDTH") <= 180
THEN
intersection(
  buffer(
   make_point($x,$y), "RADIUS"),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      make_point($x,$y),
      make_point($x + "RADIUS"*2*cos(radians(90 -  "AZIMUTH" - "BEAMWIDTH"/2 )), $y + "RADIUS"*2*sin(radians((90 - "AZIMUTH" - "BEAMWIDTH"/2 )))),
      make_point($x + "RADIUS"*2*cos(radians(90 -  "AZIMUTH" )), $y + "RADIUS"*2*sin(radians((90 - "AZIMUTH" )))),
      make_point($x + "RADIUS"*2*cos(radians(90 - "AZIMUTH" + "BEAMWIDTH" /2)), $y + "RADIUS"*2*sin(radians((90 - "AZIMUTH" + "BEAMWIDTH"/2)))),
      make_point($x,$y))
     )
    )
   )
  )

WHEN ("BEAMWIDTH") > 180
THEN
difference(
  buffer(
   make_point($x,$y), "RADIUS"),
   make_polygon(
    geom_from_wkt(
     geom_to_wkt(
      make_line(
       make_point($x,$y),
       make_point($x + "RADIUS"*2*cos(radians(90 -  "AZIMUTH" - "BEAMWIDTH"/2 )), $y + "RADIUS"*2*sin(radians((90 - "AZIMUTH" - "BEAMWIDTH"/2 )))),
       make_point($x - "RADIUS"*2*cos(radians(90 -  "AZIMUTH" )), $y - "RADIUS"*2*sin(radians((90 - "AZIMUTH" )))),
       make_point($x + "RADIUS"*2*cos(radians(90 - "AZIMUTH" + "BEAMWIDTH" /2)), $y + "RADIUS"*2*sin(radians((90 - "AZIMUTH" + "BEAMWIDTH"/2)))),
       make_point($x,$y))
      )
     )
    )
   )

END