Labeling without intersect geometries in QGIS?












3














I have a polygon geometry and I have some points that are its vertices.
QGIS 2.18 changes randomly the position of labels. When I choose 'outside of symbol' option, labels are showed outside of point symbol, but not outside of polygon.



enter image description here



I am doing many maps and I need labels to be showed like this.



enter image description here



How could I show labels of these points changing its position to be outside of the polygon automatically?



Is there any rule based solution or anything else?










share|improve this question





























    3














    I have a polygon geometry and I have some points that are its vertices.
    QGIS 2.18 changes randomly the position of labels. When I choose 'outside of symbol' option, labels are showed outside of point symbol, but not outside of polygon.



    enter image description here



    I am doing many maps and I need labels to be showed like this.



    enter image description here



    How could I show labels of these points changing its position to be outside of the polygon automatically?



    Is there any rule based solution or anything else?










    share|improve this question



























      3












      3








      3







      I have a polygon geometry and I have some points that are its vertices.
      QGIS 2.18 changes randomly the position of labels. When I choose 'outside of symbol' option, labels are showed outside of point symbol, but not outside of polygon.



      enter image description here



      I am doing many maps and I need labels to be showed like this.



      enter image description here



      How could I show labels of these points changing its position to be outside of the polygon automatically?



      Is there any rule based solution or anything else?










      share|improve this question















      I have a polygon geometry and I have some points that are its vertices.
      QGIS 2.18 changes randomly the position of labels. When I choose 'outside of symbol' option, labels are showed outside of point symbol, but not outside of polygon.



      enter image description here



      I am doing many maps and I need labels to be showed like this.



      enter image description here



      How could I show labels of these points changing its position to be outside of the polygon automatically?



      Is there any rule based solution or anything else?







      qgis labeling






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 26 '18 at 0:37









      PolyGeo

      53.3k1779238




      53.3k1779238










      asked Dec 25 '18 at 20:15









      CarolinaCarolina

      238




      238






















          1 Answer
          1






          active

          oldest

          votes


















          5














          I propose the following way




          1. Add field 'type' to your point table.

          2. Fill values of this field with the values 0 (above left point), 2 (above right point), 8 (below right point), 6 (below left point).

          3. In dialog layers properties select Labels and Rule-Based labeling.
            Labeling

          4. Press Add rule (down part of the dialog in form of a plus sign).

          5. Fill the field 'Label with' with the name of your table field (id in my case).

          6. Press the item Placement -> Quadrant -> Field type...-> Type
            Placement

          7. Set Distance (1 in millimeter)

          8. After applying those properties you get the following picture
            Labels


          9. In order to make placement of your labels automatically, you should add an action to the layer that contains polygons. That can be done by choosing Actions item of Layer properties.



          Add action




          1. Press Plus button to evoke Edit action dialog.
            Edit action


          2. Fill the proposed elements as in the picture and place the following code in the action text box



          import math



          def label_placement(bear):
          place = 0
          if bear < 22.5 or bear > 337.5:
          place = 0
          elif bear >= 22.5 and bear < 67.5:
          place = 2
          elif bear >= 67.5 and bear < 112.5:
          place = 5
          elif bear >= 112.5 and bear < 157.5:
          place = 8
          elif bear >= 157.5 and bear < 202.5:
          place = 7
          elif bear >= 202.5 and bear < 247.5:
          place = 6
          elif bear >= 247.5 and bear < 292.5:
          place = 3
          elif bear >= 292.5 and bear <= 337.5:
          place = 0

          return place


          def reverse_azimuth(az):
          if az < 180:
          az += 180
          else:
          az -= 180
          return az


          def direct_geodetic_task(pnt, dist, bear):
          deg = bear * math.pi / 180
          dx = dist * math.sin(deg)
          dy = dist * math.cos(deg)
          x = pnt.x() + dx
          y = pnt.y() + dy
          return QgsPoint(x, y)


          def point_in_poly(x, y, poly):
          n = len(poly)
          inside = False
          p1x = poly[0].x()
          p1y = poly[0].y()
          for i in range(n + 1):
          p2x = poly[i % n].x()
          p2y = poly[i % n].y()
          if y > min(p1y, p2y):
          if y <= max(p1y, p2y):
          if x <= max(p1x, p2x):
          if p1y != p2y:
          xints = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
          if p1x == p2x or x <= xints:
          inside = not inside
          p1x, p1y = p2x, p2y
          return inside


          def clear_layer(layer):
          listOfIds = [feat.id() for feat in layer.getFeatures()]
          layer.dataProvider().deleteFeatures(listOfIds)


          def bisextrix_bearing(H, A, T):
          x0 = (H.x() + T.x()) / 2
          y0 = (H.y() + T.y()) / 2

          azAH = A.azimuth(H)
          azAT = A.azimuth(T)
          return (azAH + azAT) / 2.0


          print "Ok"
          layer = None
          rectLayer = None
          layerList = QgsMapLayerRegistry.instance().mapLayersByName("as")
          if len(layerList) > 0:
          layer = layerList[0]
          else:
          print "Point table not found"

          layerList = QgsMapLayerRegistry.instance().mapLayersByName("planilha")
          if len(layerList) > 0:
          rectLayer = layerList[0]
          else:
          print "Polygon table not found"

          print layer.name()
          print rectLayer.name()

          # clear_layer(layer)

          counter = 0
          for feat in rectLayer.getFeatures():
          polys = feat.geometry().asPolygon()

          poly = polys[0]
          if len(poly) > 3:
          print counter, "Vertices=", len(poly)
          poly_len = len(poly)
          for i in range(0, poly_len - 1):
          first_ind = i - 1
          if first_ind < 0:
          first_ind = poly_len - 2
          cr0 = poly[first_ind]
          cr1 = poly[i]
          cr2 = poly[i + 1]

          counter += 1
          az = bisextrix_bearing(cr0, cr1, cr2)
          if az < 0:
          az = 360 + az

          pnt1 = direct_geodetic_task(cr1, 1, az)
          res = point_in_poly(pnt1.x(), pnt1.y(), poly)
          if res:
          az = reverse_azimuth(az)
          type = label_placement(az)

          tolerance = 10
          searchRect = QgsRectangle(pnt1.x() - tolerance,
          pnt1.y() - tolerance,
          pnt1.x() + tolerance,
          pnt1.y() + tolerance)
          request = QgsFeatureRequest()
          request.setFilterRect(searchRect)
          cnt = 0
          for ftr in layer.getFeatures(request):
          cnt += 1
          ftr.setAttribute("type", type)
          layer.updateFeature(ftr)

          # In case no features found in the vicinity of the vertex a point feature will be generated
          if cnt == 0:
          feat = QgsFeature(layer.pendingFields())
          feat.setAttribute("id", counter)
          feat.setAttribute("label", 'X-' + str(counter))
          feat.setAttribute("type", type)
          feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(cr1.x(), cr1.y())))
          (res, outFeats) = layer.dataProvider().addFeatures([feat])

          layer.triggerRepaint()




          1. In fact, the python code is included as part of the project that can be found by the GitHub link https://github.com/ulabnit07/12
            You can find a Qgis project example.qgs and all the rest files.




            1. After opening example.qgs you can try to launch the action Generate points on the layer rectangle that performs the desired function.
              Result




          Do not hesitate to ask if anything unclear from what I explained.






          share|improve this answer























          • It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
            – Carolina
            Dec 26 '18 at 12:20










          • Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
            – Vadym
            Dec 26 '18 at 13:15












          • Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
            – Carolina
            Dec 27 '18 at 1:42










          • Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
            – Carolina
            Jan 1 at 16:30






          • 1




            I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
            – Vadym
            Jan 2 at 11:07











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "79"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f306978%2flabeling-without-intersect-geometries-in-qgis%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          5














          I propose the following way




          1. Add field 'type' to your point table.

          2. Fill values of this field with the values 0 (above left point), 2 (above right point), 8 (below right point), 6 (below left point).

          3. In dialog layers properties select Labels and Rule-Based labeling.
            Labeling

          4. Press Add rule (down part of the dialog in form of a plus sign).

          5. Fill the field 'Label with' with the name of your table field (id in my case).

          6. Press the item Placement -> Quadrant -> Field type...-> Type
            Placement

          7. Set Distance (1 in millimeter)

          8. After applying those properties you get the following picture
            Labels


          9. In order to make placement of your labels automatically, you should add an action to the layer that contains polygons. That can be done by choosing Actions item of Layer properties.



          Add action




          1. Press Plus button to evoke Edit action dialog.
            Edit action


          2. Fill the proposed elements as in the picture and place the following code in the action text box



          import math



          def label_placement(bear):
          place = 0
          if bear < 22.5 or bear > 337.5:
          place = 0
          elif bear >= 22.5 and bear < 67.5:
          place = 2
          elif bear >= 67.5 and bear < 112.5:
          place = 5
          elif bear >= 112.5 and bear < 157.5:
          place = 8
          elif bear >= 157.5 and bear < 202.5:
          place = 7
          elif bear >= 202.5 and bear < 247.5:
          place = 6
          elif bear >= 247.5 and bear < 292.5:
          place = 3
          elif bear >= 292.5 and bear <= 337.5:
          place = 0

          return place


          def reverse_azimuth(az):
          if az < 180:
          az += 180
          else:
          az -= 180
          return az


          def direct_geodetic_task(pnt, dist, bear):
          deg = bear * math.pi / 180
          dx = dist * math.sin(deg)
          dy = dist * math.cos(deg)
          x = pnt.x() + dx
          y = pnt.y() + dy
          return QgsPoint(x, y)


          def point_in_poly(x, y, poly):
          n = len(poly)
          inside = False
          p1x = poly[0].x()
          p1y = poly[0].y()
          for i in range(n + 1):
          p2x = poly[i % n].x()
          p2y = poly[i % n].y()
          if y > min(p1y, p2y):
          if y <= max(p1y, p2y):
          if x <= max(p1x, p2x):
          if p1y != p2y:
          xints = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
          if p1x == p2x or x <= xints:
          inside = not inside
          p1x, p1y = p2x, p2y
          return inside


          def clear_layer(layer):
          listOfIds = [feat.id() for feat in layer.getFeatures()]
          layer.dataProvider().deleteFeatures(listOfIds)


          def bisextrix_bearing(H, A, T):
          x0 = (H.x() + T.x()) / 2
          y0 = (H.y() + T.y()) / 2

          azAH = A.azimuth(H)
          azAT = A.azimuth(T)
          return (azAH + azAT) / 2.0


          print "Ok"
          layer = None
          rectLayer = None
          layerList = QgsMapLayerRegistry.instance().mapLayersByName("as")
          if len(layerList) > 0:
          layer = layerList[0]
          else:
          print "Point table not found"

          layerList = QgsMapLayerRegistry.instance().mapLayersByName("planilha")
          if len(layerList) > 0:
          rectLayer = layerList[0]
          else:
          print "Polygon table not found"

          print layer.name()
          print rectLayer.name()

          # clear_layer(layer)

          counter = 0
          for feat in rectLayer.getFeatures():
          polys = feat.geometry().asPolygon()

          poly = polys[0]
          if len(poly) > 3:
          print counter, "Vertices=", len(poly)
          poly_len = len(poly)
          for i in range(0, poly_len - 1):
          first_ind = i - 1
          if first_ind < 0:
          first_ind = poly_len - 2
          cr0 = poly[first_ind]
          cr1 = poly[i]
          cr2 = poly[i + 1]

          counter += 1
          az = bisextrix_bearing(cr0, cr1, cr2)
          if az < 0:
          az = 360 + az

          pnt1 = direct_geodetic_task(cr1, 1, az)
          res = point_in_poly(pnt1.x(), pnt1.y(), poly)
          if res:
          az = reverse_azimuth(az)
          type = label_placement(az)

          tolerance = 10
          searchRect = QgsRectangle(pnt1.x() - tolerance,
          pnt1.y() - tolerance,
          pnt1.x() + tolerance,
          pnt1.y() + tolerance)
          request = QgsFeatureRequest()
          request.setFilterRect(searchRect)
          cnt = 0
          for ftr in layer.getFeatures(request):
          cnt += 1
          ftr.setAttribute("type", type)
          layer.updateFeature(ftr)

          # In case no features found in the vicinity of the vertex a point feature will be generated
          if cnt == 0:
          feat = QgsFeature(layer.pendingFields())
          feat.setAttribute("id", counter)
          feat.setAttribute("label", 'X-' + str(counter))
          feat.setAttribute("type", type)
          feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(cr1.x(), cr1.y())))
          (res, outFeats) = layer.dataProvider().addFeatures([feat])

          layer.triggerRepaint()




          1. In fact, the python code is included as part of the project that can be found by the GitHub link https://github.com/ulabnit07/12
            You can find a Qgis project example.qgs and all the rest files.




            1. After opening example.qgs you can try to launch the action Generate points on the layer rectangle that performs the desired function.
              Result




          Do not hesitate to ask if anything unclear from what I explained.






          share|improve this answer























          • It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
            – Carolina
            Dec 26 '18 at 12:20










          • Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
            – Vadym
            Dec 26 '18 at 13:15












          • Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
            – Carolina
            Dec 27 '18 at 1:42










          • Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
            – Carolina
            Jan 1 at 16:30






          • 1




            I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
            – Vadym
            Jan 2 at 11:07
















          5














          I propose the following way




          1. Add field 'type' to your point table.

          2. Fill values of this field with the values 0 (above left point), 2 (above right point), 8 (below right point), 6 (below left point).

          3. In dialog layers properties select Labels and Rule-Based labeling.
            Labeling

          4. Press Add rule (down part of the dialog in form of a plus sign).

          5. Fill the field 'Label with' with the name of your table field (id in my case).

          6. Press the item Placement -> Quadrant -> Field type...-> Type
            Placement

          7. Set Distance (1 in millimeter)

          8. After applying those properties you get the following picture
            Labels


          9. In order to make placement of your labels automatically, you should add an action to the layer that contains polygons. That can be done by choosing Actions item of Layer properties.



          Add action




          1. Press Plus button to evoke Edit action dialog.
            Edit action


          2. Fill the proposed elements as in the picture and place the following code in the action text box



          import math



          def label_placement(bear):
          place = 0
          if bear < 22.5 or bear > 337.5:
          place = 0
          elif bear >= 22.5 and bear < 67.5:
          place = 2
          elif bear >= 67.5 and bear < 112.5:
          place = 5
          elif bear >= 112.5 and bear < 157.5:
          place = 8
          elif bear >= 157.5 and bear < 202.5:
          place = 7
          elif bear >= 202.5 and bear < 247.5:
          place = 6
          elif bear >= 247.5 and bear < 292.5:
          place = 3
          elif bear >= 292.5 and bear <= 337.5:
          place = 0

          return place


          def reverse_azimuth(az):
          if az < 180:
          az += 180
          else:
          az -= 180
          return az


          def direct_geodetic_task(pnt, dist, bear):
          deg = bear * math.pi / 180
          dx = dist * math.sin(deg)
          dy = dist * math.cos(deg)
          x = pnt.x() + dx
          y = pnt.y() + dy
          return QgsPoint(x, y)


          def point_in_poly(x, y, poly):
          n = len(poly)
          inside = False
          p1x = poly[0].x()
          p1y = poly[0].y()
          for i in range(n + 1):
          p2x = poly[i % n].x()
          p2y = poly[i % n].y()
          if y > min(p1y, p2y):
          if y <= max(p1y, p2y):
          if x <= max(p1x, p2x):
          if p1y != p2y:
          xints = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
          if p1x == p2x or x <= xints:
          inside = not inside
          p1x, p1y = p2x, p2y
          return inside


          def clear_layer(layer):
          listOfIds = [feat.id() for feat in layer.getFeatures()]
          layer.dataProvider().deleteFeatures(listOfIds)


          def bisextrix_bearing(H, A, T):
          x0 = (H.x() + T.x()) / 2
          y0 = (H.y() + T.y()) / 2

          azAH = A.azimuth(H)
          azAT = A.azimuth(T)
          return (azAH + azAT) / 2.0


          print "Ok"
          layer = None
          rectLayer = None
          layerList = QgsMapLayerRegistry.instance().mapLayersByName("as")
          if len(layerList) > 0:
          layer = layerList[0]
          else:
          print "Point table not found"

          layerList = QgsMapLayerRegistry.instance().mapLayersByName("planilha")
          if len(layerList) > 0:
          rectLayer = layerList[0]
          else:
          print "Polygon table not found"

          print layer.name()
          print rectLayer.name()

          # clear_layer(layer)

          counter = 0
          for feat in rectLayer.getFeatures():
          polys = feat.geometry().asPolygon()

          poly = polys[0]
          if len(poly) > 3:
          print counter, "Vertices=", len(poly)
          poly_len = len(poly)
          for i in range(0, poly_len - 1):
          first_ind = i - 1
          if first_ind < 0:
          first_ind = poly_len - 2
          cr0 = poly[first_ind]
          cr1 = poly[i]
          cr2 = poly[i + 1]

          counter += 1
          az = bisextrix_bearing(cr0, cr1, cr2)
          if az < 0:
          az = 360 + az

          pnt1 = direct_geodetic_task(cr1, 1, az)
          res = point_in_poly(pnt1.x(), pnt1.y(), poly)
          if res:
          az = reverse_azimuth(az)
          type = label_placement(az)

          tolerance = 10
          searchRect = QgsRectangle(pnt1.x() - tolerance,
          pnt1.y() - tolerance,
          pnt1.x() + tolerance,
          pnt1.y() + tolerance)
          request = QgsFeatureRequest()
          request.setFilterRect(searchRect)
          cnt = 0
          for ftr in layer.getFeatures(request):
          cnt += 1
          ftr.setAttribute("type", type)
          layer.updateFeature(ftr)

          # In case no features found in the vicinity of the vertex a point feature will be generated
          if cnt == 0:
          feat = QgsFeature(layer.pendingFields())
          feat.setAttribute("id", counter)
          feat.setAttribute("label", 'X-' + str(counter))
          feat.setAttribute("type", type)
          feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(cr1.x(), cr1.y())))
          (res, outFeats) = layer.dataProvider().addFeatures([feat])

          layer.triggerRepaint()




          1. In fact, the python code is included as part of the project that can be found by the GitHub link https://github.com/ulabnit07/12
            You can find a Qgis project example.qgs and all the rest files.




            1. After opening example.qgs you can try to launch the action Generate points on the layer rectangle that performs the desired function.
              Result




          Do not hesitate to ask if anything unclear from what I explained.






          share|improve this answer























          • It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
            – Carolina
            Dec 26 '18 at 12:20










          • Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
            – Vadym
            Dec 26 '18 at 13:15












          • Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
            – Carolina
            Dec 27 '18 at 1:42










          • Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
            – Carolina
            Jan 1 at 16:30






          • 1




            I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
            – Vadym
            Jan 2 at 11:07














          5












          5








          5






          I propose the following way




          1. Add field 'type' to your point table.

          2. Fill values of this field with the values 0 (above left point), 2 (above right point), 8 (below right point), 6 (below left point).

          3. In dialog layers properties select Labels and Rule-Based labeling.
            Labeling

          4. Press Add rule (down part of the dialog in form of a plus sign).

          5. Fill the field 'Label with' with the name of your table field (id in my case).

          6. Press the item Placement -> Quadrant -> Field type...-> Type
            Placement

          7. Set Distance (1 in millimeter)

          8. After applying those properties you get the following picture
            Labels


          9. In order to make placement of your labels automatically, you should add an action to the layer that contains polygons. That can be done by choosing Actions item of Layer properties.



          Add action




          1. Press Plus button to evoke Edit action dialog.
            Edit action


          2. Fill the proposed elements as in the picture and place the following code in the action text box



          import math



          def label_placement(bear):
          place = 0
          if bear < 22.5 or bear > 337.5:
          place = 0
          elif bear >= 22.5 and bear < 67.5:
          place = 2
          elif bear >= 67.5 and bear < 112.5:
          place = 5
          elif bear >= 112.5 and bear < 157.5:
          place = 8
          elif bear >= 157.5 and bear < 202.5:
          place = 7
          elif bear >= 202.5 and bear < 247.5:
          place = 6
          elif bear >= 247.5 and bear < 292.5:
          place = 3
          elif bear >= 292.5 and bear <= 337.5:
          place = 0

          return place


          def reverse_azimuth(az):
          if az < 180:
          az += 180
          else:
          az -= 180
          return az


          def direct_geodetic_task(pnt, dist, bear):
          deg = bear * math.pi / 180
          dx = dist * math.sin(deg)
          dy = dist * math.cos(deg)
          x = pnt.x() + dx
          y = pnt.y() + dy
          return QgsPoint(x, y)


          def point_in_poly(x, y, poly):
          n = len(poly)
          inside = False
          p1x = poly[0].x()
          p1y = poly[0].y()
          for i in range(n + 1):
          p2x = poly[i % n].x()
          p2y = poly[i % n].y()
          if y > min(p1y, p2y):
          if y <= max(p1y, p2y):
          if x <= max(p1x, p2x):
          if p1y != p2y:
          xints = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
          if p1x == p2x or x <= xints:
          inside = not inside
          p1x, p1y = p2x, p2y
          return inside


          def clear_layer(layer):
          listOfIds = [feat.id() for feat in layer.getFeatures()]
          layer.dataProvider().deleteFeatures(listOfIds)


          def bisextrix_bearing(H, A, T):
          x0 = (H.x() + T.x()) / 2
          y0 = (H.y() + T.y()) / 2

          azAH = A.azimuth(H)
          azAT = A.azimuth(T)
          return (azAH + azAT) / 2.0


          print "Ok"
          layer = None
          rectLayer = None
          layerList = QgsMapLayerRegistry.instance().mapLayersByName("as")
          if len(layerList) > 0:
          layer = layerList[0]
          else:
          print "Point table not found"

          layerList = QgsMapLayerRegistry.instance().mapLayersByName("planilha")
          if len(layerList) > 0:
          rectLayer = layerList[0]
          else:
          print "Polygon table not found"

          print layer.name()
          print rectLayer.name()

          # clear_layer(layer)

          counter = 0
          for feat in rectLayer.getFeatures():
          polys = feat.geometry().asPolygon()

          poly = polys[0]
          if len(poly) > 3:
          print counter, "Vertices=", len(poly)
          poly_len = len(poly)
          for i in range(0, poly_len - 1):
          first_ind = i - 1
          if first_ind < 0:
          first_ind = poly_len - 2
          cr0 = poly[first_ind]
          cr1 = poly[i]
          cr2 = poly[i + 1]

          counter += 1
          az = bisextrix_bearing(cr0, cr1, cr2)
          if az < 0:
          az = 360 + az

          pnt1 = direct_geodetic_task(cr1, 1, az)
          res = point_in_poly(pnt1.x(), pnt1.y(), poly)
          if res:
          az = reverse_azimuth(az)
          type = label_placement(az)

          tolerance = 10
          searchRect = QgsRectangle(pnt1.x() - tolerance,
          pnt1.y() - tolerance,
          pnt1.x() + tolerance,
          pnt1.y() + tolerance)
          request = QgsFeatureRequest()
          request.setFilterRect(searchRect)
          cnt = 0
          for ftr in layer.getFeatures(request):
          cnt += 1
          ftr.setAttribute("type", type)
          layer.updateFeature(ftr)

          # In case no features found in the vicinity of the vertex a point feature will be generated
          if cnt == 0:
          feat = QgsFeature(layer.pendingFields())
          feat.setAttribute("id", counter)
          feat.setAttribute("label", 'X-' + str(counter))
          feat.setAttribute("type", type)
          feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(cr1.x(), cr1.y())))
          (res, outFeats) = layer.dataProvider().addFeatures([feat])

          layer.triggerRepaint()




          1. In fact, the python code is included as part of the project that can be found by the GitHub link https://github.com/ulabnit07/12
            You can find a Qgis project example.qgs and all the rest files.




            1. After opening example.qgs you can try to launch the action Generate points on the layer rectangle that performs the desired function.
              Result




          Do not hesitate to ask if anything unclear from what I explained.






          share|improve this answer














          I propose the following way




          1. Add field 'type' to your point table.

          2. Fill values of this field with the values 0 (above left point), 2 (above right point), 8 (below right point), 6 (below left point).

          3. In dialog layers properties select Labels and Rule-Based labeling.
            Labeling

          4. Press Add rule (down part of the dialog in form of a plus sign).

          5. Fill the field 'Label with' with the name of your table field (id in my case).

          6. Press the item Placement -> Quadrant -> Field type...-> Type
            Placement

          7. Set Distance (1 in millimeter)

          8. After applying those properties you get the following picture
            Labels


          9. In order to make placement of your labels automatically, you should add an action to the layer that contains polygons. That can be done by choosing Actions item of Layer properties.



          Add action




          1. Press Plus button to evoke Edit action dialog.
            Edit action


          2. Fill the proposed elements as in the picture and place the following code in the action text box



          import math



          def label_placement(bear):
          place = 0
          if bear < 22.5 or bear > 337.5:
          place = 0
          elif bear >= 22.5 and bear < 67.5:
          place = 2
          elif bear >= 67.5 and bear < 112.5:
          place = 5
          elif bear >= 112.5 and bear < 157.5:
          place = 8
          elif bear >= 157.5 and bear < 202.5:
          place = 7
          elif bear >= 202.5 and bear < 247.5:
          place = 6
          elif bear >= 247.5 and bear < 292.5:
          place = 3
          elif bear >= 292.5 and bear <= 337.5:
          place = 0

          return place


          def reverse_azimuth(az):
          if az < 180:
          az += 180
          else:
          az -= 180
          return az


          def direct_geodetic_task(pnt, dist, bear):
          deg = bear * math.pi / 180
          dx = dist * math.sin(deg)
          dy = dist * math.cos(deg)
          x = pnt.x() + dx
          y = pnt.y() + dy
          return QgsPoint(x, y)


          def point_in_poly(x, y, poly):
          n = len(poly)
          inside = False
          p1x = poly[0].x()
          p1y = poly[0].y()
          for i in range(n + 1):
          p2x = poly[i % n].x()
          p2y = poly[i % n].y()
          if y > min(p1y, p2y):
          if y <= max(p1y, p2y):
          if x <= max(p1x, p2x):
          if p1y != p2y:
          xints = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
          if p1x == p2x or x <= xints:
          inside = not inside
          p1x, p1y = p2x, p2y
          return inside


          def clear_layer(layer):
          listOfIds = [feat.id() for feat in layer.getFeatures()]
          layer.dataProvider().deleteFeatures(listOfIds)


          def bisextrix_bearing(H, A, T):
          x0 = (H.x() + T.x()) / 2
          y0 = (H.y() + T.y()) / 2

          azAH = A.azimuth(H)
          azAT = A.azimuth(T)
          return (azAH + azAT) / 2.0


          print "Ok"
          layer = None
          rectLayer = None
          layerList = QgsMapLayerRegistry.instance().mapLayersByName("as")
          if len(layerList) > 0:
          layer = layerList[0]
          else:
          print "Point table not found"

          layerList = QgsMapLayerRegistry.instance().mapLayersByName("planilha")
          if len(layerList) > 0:
          rectLayer = layerList[0]
          else:
          print "Polygon table not found"

          print layer.name()
          print rectLayer.name()

          # clear_layer(layer)

          counter = 0
          for feat in rectLayer.getFeatures():
          polys = feat.geometry().asPolygon()

          poly = polys[0]
          if len(poly) > 3:
          print counter, "Vertices=", len(poly)
          poly_len = len(poly)
          for i in range(0, poly_len - 1):
          first_ind = i - 1
          if first_ind < 0:
          first_ind = poly_len - 2
          cr0 = poly[first_ind]
          cr1 = poly[i]
          cr2 = poly[i + 1]

          counter += 1
          az = bisextrix_bearing(cr0, cr1, cr2)
          if az < 0:
          az = 360 + az

          pnt1 = direct_geodetic_task(cr1, 1, az)
          res = point_in_poly(pnt1.x(), pnt1.y(), poly)
          if res:
          az = reverse_azimuth(az)
          type = label_placement(az)

          tolerance = 10
          searchRect = QgsRectangle(pnt1.x() - tolerance,
          pnt1.y() - tolerance,
          pnt1.x() + tolerance,
          pnt1.y() + tolerance)
          request = QgsFeatureRequest()
          request.setFilterRect(searchRect)
          cnt = 0
          for ftr in layer.getFeatures(request):
          cnt += 1
          ftr.setAttribute("type", type)
          layer.updateFeature(ftr)

          # In case no features found in the vicinity of the vertex a point feature will be generated
          if cnt == 0:
          feat = QgsFeature(layer.pendingFields())
          feat.setAttribute("id", counter)
          feat.setAttribute("label", 'X-' + str(counter))
          feat.setAttribute("type", type)
          feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(cr1.x(), cr1.y())))
          (res, outFeats) = layer.dataProvider().addFeatures([feat])

          layer.triggerRepaint()




          1. In fact, the python code is included as part of the project that can be found by the GitHub link https://github.com/ulabnit07/12
            You can find a Qgis project example.qgs and all the rest files.




            1. After opening example.qgs you can try to launch the action Generate points on the layer rectangle that performs the desired function.
              Result




          Do not hesitate to ask if anything unclear from what I explained.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 3 at 0:26

























          answered Dec 25 '18 at 23:11









          VadymVadym

          39117




          39117












          • It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
            – Carolina
            Dec 26 '18 at 12:20










          • Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
            – Vadym
            Dec 26 '18 at 13:15












          • Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
            – Carolina
            Dec 27 '18 at 1:42










          • Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
            – Carolina
            Jan 1 at 16:30






          • 1




            I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
            – Vadym
            Jan 2 at 11:07


















          • It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
            – Carolina
            Dec 26 '18 at 12:20










          • Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
            – Vadym
            Dec 26 '18 at 13:15












          • Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
            – Carolina
            Dec 27 '18 at 1:42










          • Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
            – Carolina
            Jan 1 at 16:30






          • 1




            I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
            – Vadym
            Jan 2 at 11:07
















          It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
          – Carolina
          Dec 26 '18 at 12:20




          It is very helpful and a good solution for few geometries, but I have about 300 geometries to put these numbers at attribute table. Is there a not manually way to put them? An expression that defines their position related to polygon? Unfortunately I am not finding a solution.
          – Carolina
          Dec 26 '18 at 12:20












          Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
          – Vadym
          Dec 26 '18 at 13:15






          Actually, I can't see the possibility to build such an expression inside Edit rule dialog. But we can generate point features of some layer with a value of the mentioned field 'type' and then assign the qml style to this point layer. After that the proper position of the labels guaranteed. This way can be done with some specific python code. Are all of your rectangle geometries included in one layer?
          – Vadym
          Dec 26 '18 at 13:15














          Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
          – Carolina
          Dec 27 '18 at 1:42




          Yes, they are all included in one layer, but they are not all rectangles. Most of them have irregular shape.
          – Carolina
          Dec 27 '18 at 1:42












          Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
          – Carolina
          Jan 1 at 16:30




          Your last edition worked exactly as I need. Thank you very much! I just have to understand your code to change the part that it clears all the attribute table of the point layer and it just leaves 'id' and 'type' data, because I already have a column with label and another with important data. Does it seem complicated to do?
          – Carolina
          Jan 1 at 16:30




          1




          1




          I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
          – Vadym
          Jan 2 at 11:07




          I've changed the python code. The better way to use the modified code is to download files from the GitHub link github.com/ulabnit07/12
          – Vadym
          Jan 2 at 11:07


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Geographic Information Systems Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f306978%2flabeling-without-intersect-geometries-in-qgis%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Probability when a professor distributes a quiz and homework assignment to a class of n students.

          Aardman Animations

          Are they similar matrix