Saturday 15 December 2018

QGIS Plugin: Circle ring sector

This plugins creates polygon that is sector of circle ring as name suggests. But how can it be use in aviation? Sometimes lateral limit of airspace is defined as arcs between bearings (clockwise and anti-clockwise), strait lines between between bearings at given radius.

Again, this plugin can be though as further extension of previous ones related to polygon that shape is based on circle and its parts.
Boundary of polygon can be described as:
  • vertices A: defined by bearing 'from' and inner radius
  • 'strait line' from A to next vertex (B)
  • vertices B: defined by bearing 'from' and outer radius
  • vertices on clockwise arc, outer radius
  • vertices C: defined by bearing 'to' and outer radius
  • 'strait' line from C to next vertex (D)
  • vertices D: defined by bearing 'to' and inner radius
  • vertices on anti-clockwise arc, inner radius
  • vertex A
 I am not going to discuss here how to check input data and etc. - it is done the same way as in teh previous plugins. So let's go to method add_circle_ring_sector() that is called when button Add is pressed. First, calculation of  coordinates of vertices A-D:


a_lat, a_lon = ct.vincenty_direct_solution(self.circ_center.dd_lat,
                                           self.circ_center.dd_lon,
                                           self.brng_from.dd_tbrng,
                                           self.radius_inner_m,
                                           ct.WGS84_A,
                                           ct.WGS84_B,
                                           ct.WGS84_F)
b_lat, b_lon = ct.vincenty_direct_solution(self.circ_center.dd_lat,
                                           self.circ_center.dd_lon,
                                           self.brng_from.dd_tbrng,
                                           self.radius_outer_m,
                                           ct.WGS84_A,
                                           ct.WGS84_B,
                                           ct.WGS84_F)
c_lat, c_lon = ct.vincenty_direct_solution(self.circ_center.dd_lat,
                                           self.circ_center.dd_lon,
                                           self.brng_to.dd_tbrng,
                                           self.radius_outer_m,
                                           ct.WGS84_A,
                                           ct.WGS84_B,
                                           ct.WGS84_F)
d_lat, d_lon = ct.vincenty_direct_solution(self.circ_center.dd_lat,
                                           self.circ_center.dd_lon,
                                           self.brng_to.dd_tbrng,
                                           self.radius_inner_m,
                                           ct.WGS84_A,
                                           ct.WGS84_B,
                                           ct.WGS84_F)

a_vertex = QgsPointXY(a_lon, a_lat)
b_vertex = QgsPointXY(b_lon, b_lat)
c_vertex = QgsPointXY(c_lon, c_lat)
d_vertex = QgsPointXY(d_lon, d_lat)

Now, we can start creating list of QgsPointXY objetcs that will be passed to method that creates polygon and adds it to memory layer:

poly_vertices = []
poly_vertices.append(a_vertex)
poly_vertices.append(b_vertex)

Vertices on arcs will be calculated in for loop, so we need to get what is the angle between from and to bearings:

arc_angle = math.floor(self.brng_to.dd_tbrng) - math.ceil(self.brng_from.dd_tbrng)
if arc_angle < 0:
    arc_angle += 360
elif arc_angle > 360:
    arc_angle -= 360

Calculating vertices on clockwise arc:


for i in range(0, arc_angle + 1):
    vertex_lat, vertex_lon = ct.vincenty_direct_solution(self.circ_center.dd_lat,
                                                         self.circ_center.dd_lon,
                                                         math.ceil(self.brng_from.dd_tbrng) + i,
                                                         self.radius_outer_m,
                                                         ct.WGS84_A,
                                                         ct.WGS84_B,
                                                         ct.WGS84_F)

    arc_vertex = QgsPointXY(vertex_lon, vertex_lat)
    poly_vertices.append(arc_vertex)

poly_vertices.append(c_vertex)
poly_vertices.append(d_vertex)

Calculating vertices on anti-clockwise arc:


for i in range(0, arc_angle + 1):
    vertex_lat, vertex_lon = ct.vincenty_direct_solution(self.circ_center.dd_lat,
                                                         self.circ_center.dd_lon,
                                                         math.floor(self.brng_to.dd_tbrng) - i,
                                                         self.radius_inner_m,
                                                         ct.WGS84_A,
                                                         ct.WGS84_B,
                                                         ct.WGS84_F)

    arc_vertex = QgsPointXY(vertex_lon, vertex_lat)
    poly_vertices.append(arc_vertex)

And append first-last vertex to the list:


poly_vertices.append(a_vertex)

Full source code and plugin can be download from: https://github.com/strpaw/QGIS3-CreateCircleRingSector-plugin

No comments:

Post a Comment