11

I want to show a cellular network on a map. Input data is a .csv file where each string is a cellular sector. The attributes are: sector id, its coordinates, its azimuth and an angle of antenna beam width.

Antenna beam width values are in a range of 30 to 360 degrees. 360 antenna beam width means that it must be shown on the map as a circle. Antennas with other beam widths must be shown as a sectors with appropriate aperture angles.

enter image description here

Is it possible to show the antennas using symbols only? I know how to create my own SVG symbol and hope to find how to rotate it according to the azimuth. But is there any way to apply variable antenna beam width according to its attribute value from 30 to 360 degrees?

I think the symbols are the best way to draw the antennas because of dynamic visualization on the map according to the scale of view, if this way is possible in QGIS.

Of course, the task can be solved by drawing appropriate polygons as a layer feature, but that would be a workaround solution.

  • So you need to draw the arc in the right direction which is different for each site? – Nathan W Feb 22 '16 at 10:59
  • Not at all If I understand properly. It must be a sector of circle (or the whole circle in case of beamwidth = 360) as its shown in the picture. – E Bobrov Feb 22 '16 at 11:11
  • Yeah that is what I mean. – Nathan W Feb 22 '16 at 11:11
  • Ok, I see. Speaking in general the arc symbol is not needed strictly. The main attributes are azimuth and beamwidth. I can use any symbol to draw the antennas not an arc only. – E Bobrov Feb 22 '16 at 11:17
  • Probably I have found the example which may help: Creating Custom Symbol Layer Types. But I`m not sure. So anybody tried to create your own symbol layer class that draws for example each layer feature direction depending on its attribute (i.e. antenna azimuth in the words of picture above)? – E Bobrov Mar 23 '17 at 19:56
7

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

10

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).

  • Were you looking for this solution? Does it work? – mgri Mar 27 '17 at 8:34
  • Your soluton totally solve the case described in the topic! I`ve implemented it and understood that my own real case is slightly different. Sorry that is my fault. – E Bobrov Mar 27 '17 at 8:56
  • 1) The density of my sectors on the map is defferent, i.e. in case of short distances between sectors the defined distance in the code will give a lot of sectors overlapping, changing the map zoom wouldn`t help, so it will be rather hard to read the map. But in cases of long distances between sectors showed sectors will be very small and maybe hard to read the map. Ussing single symbols is free of that problem, their scales change with a map zooming. – E Bobrov Mar 27 '17 at 8:56
  • 2) And there are beamwidth distortions: beamwidth 360 degrees look like ellipses, sectors with different azimuths but the same beamwidth do not look like like sectors with equvivalent beamwidths. Does it because I am ussing Geographic Coordinate System? You now, different angles of longitude/latitude represent different distance between points on the earth. So the solution needed to be localized to the Earth areas where sectors are located. – E Bobrov Mar 27 '17 at 8:56
  • Anyway your solution and the reference for similar answer "Creating sector lights in QGIS?" helped me to see some useful functionality. Thank you again. – E Bobrov Mar 27 '17 at 8:57
4

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
  • My answer proposed a general approach: since there were a lot of variables involved in the issue, it was quite impossible to create a unique procedure for solving any situation. So, thanks for pointing it and proposing an approach with MultiPoint features, it will surely help someone in the future. – mgri Oct 20 '17 at 16:16
1

I was gifted with partial solution in the web without any additional plugins, just qgis out of the box. It does not show antenna beamwidth, just rotate simple marker in the right direction: use simple marker and rotate it with antenna azimuth + 180 degrees (Layer Properties>Single Simbol->Marker->Simple marker->triangle->rotation->edit->type <180 + "antenna azimuth"> in the expression field. And also set Top in the Anchor point field of the marker). Ussing <180 + "antenna azimuth"> is needed because of inappropriate direction of the embeded simple triangle marker. Otherwise it will show wrong antenna direction.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.