Related Plugins and Tags

QGIS Planet

QGIS gets Oracle support!

Seems this is a good day for QGIS Oracle users. According this commit made by Jürgen QGIS now has built-in Oracle support. Win!

Native Oracle support can now see QGIS being opened up to a wider user base yet again. A large user base normally means more people willing to sponsor awesome new features and bug fixes. Having seen the growth in the user base from having native MS SQL Server 2008+ support I can imagine what it will be like with Oracle.

The list of formats QGIS can open and edit is getting larger and larger with each release. Is there a future for vendor lock in? I can’t see it.

Standard disclaimer about latest dev build and new features :)


Filed under: Open Source, qgis Tagged: FOSSGIS, gis, Open Source, oracle, osgeo, qgis, qgis-editing, Quantum GIS

QGIS gets Oracle support!

Seems this is a good day for QGIS Oracle users. According this commit made by Jürgen QGIS now has built-in Oracle support. Win!

Native Oracle support can now see QGIS being opened up to a wider user base yet again. A large user base normally means more people willing to sponsor awesome new features and bug fixes. Having seen the growth in the user base from having native MS SQL Server 2008+ support I can imagine what it will be like with Oracle.

The list of formats QGIS can open and edit is getting larger and larger with each release. Is there a future for vendor lock in? I can't see it.

Standard disclaimer about latest dev build and new features :)

QGIS gets Oracle support!

  • Open Source
  • qgis tags:
  • FOSSGIS
  • gis
  • Open Source
  • oracle
  • osgeo
  • qgis
  • qgis-editing
  • Quantum GIS

Seems this is a good day for QGIS Oracle users. According this commit made by Jürgen QGIS now has built-in Oracle support. Win!

Native Oracle support can now see QGIS being opened up to a wider user base yet again. A large user base normally means more people willing to sponsor awesome new features and bug fixes. Having seen the growth in the user base from having native MS SQL Server 2008+ support I can imagine what it will be like with Oracle.

The list of formats QGIS can open and edit is getting larger and larger with each release. Is there a future for vendor lock in? I can't see it.

Standard disclaimer about latest dev build and new features :)

QGIS gets Oracle support!

  • Open Source
  • qgis tags:
  • FOSSGIS
  • gis
  • Open Source
  • oracle
  • osgeo
  • qgis
  • qgis-editing
  • Quantum GIS

Seems this is a good day for QGIS Oracle users. According this commit made by Jürgen QGIS now has built-in Oracle support. Win!

Native Oracle support can now see QGIS being opened up to a wider user base yet again. A large user base normally means more people willing to sponsor awesome new features and bug fixes. Having seen the growth in the user base from having native MS SQL Server 2008+ support I can imagine what it will be like with Oracle.

The list of formats QGIS can open and edit is getting larger and larger with each release. Is there a future for vendor lock in? I can't see it.

Standard disclaimer about latest dev build and new features :)

Geo-Processing in QGIS

I’m going to look at the geo-processing tools. The geo-processing tools are found on the Vector menu under Geo-processing tools. These tools do not edit the input tables; instead you are prompted to create a new layer for the results. Therefore the input layers don’t need to be editable. You can choose to carry out the operation on every feature in the chosen layers, or just the selected features. These functions can be combined with attribute updates and calculations to carry out more complex analysis (e.g. calculate proportional overlap) or to count the address points within set distances of proposed new roads.

I will carry out most of the operations on the green square and red circle shown below:-

QGIS map window

QGIS map window


Intersect creates a new feature based on the area of overlap (the intersection) between the two layers. The attributes from both source layers are copied to the new feature:-

Intersect in QGIS

Intersect in QGIS

To calculate the area of overlap, update the newly created feature’s attribute table with its area.

Union creates a new layer that covers the combined features

Union in QGIS

Symmetrical Difference creates new shapes based on the non overlapping areas of the original features:-

Symmetrical Difference in QGIS

Clip creates a new shape based on the area of the input layer that is overlapped by the clipping layer. It is similar to the intersection but differs in that the attributes of the chosen layer only are copied to the new feature. It is similar to MapInfo’s Erase Outside function.

Clip in QGIS

Difference creates a new feature based on the area of the input layer that isn’t overlapped by the clipping layer. It is similar to MapInfo’s Erase function.

Difference in QGIS

Dissolve breaks apart overlapping regions in the same layer.

Buffer creates a region around each feature in the source layer. I have used buffers to count address points within set distances of new roads, assign address points to local amenity catchment zones etc. In this case I’m going to apply a 100m buffer around overhead electricity lines. These can be downloaded from OS Open Data.:-

Buffer in QGIS

  • Input vector Layer – the layer that contains the source objects
  • Buffer Distance – the distance the buffer will extend from the source objects
  • Buffer Distance Field – alternatively QGIS can use a value from a numeric field, this makes drawing variable width buffers for features in the same layer easy e.g. Sites rated High Sensitivity could be updated with a buffer distance of 1,000m, sites rated Medium Sensitivity could be updated with a buffer distance of 500m.
  • Dissolve Buffer Results. The default is to combine the buffers into one region. Enabling this creates a separate region for each source object.

Creating a simple habitat selection model for the Common Buzzard using the data from the Sobibor Forest District.

New QGIS PDF and HTML manuals

A quick update from the QGIS documentation team today on the mailing list. The QGIS 1.8 manual is now available in HTML and PDF form.

HTML manual can be found at: http://docs.qgis.org/html/en/docs/user_manual/index.html

PDF manual at: http://docs.qgis.org/pdf/QGIS-1.8-UserGuide-en.pdf

This has been part of an ongoing effort from the documentation team since before the 1.8 release to bring our all our documentation into reStructedText rather then LaTeX. Moving to reStructedText allows quicker updates and a larger range of final output formats.

I would like to thank everyone who has been involved in this process as I know what a grueling process updating documentation can be.

Community notice

Just remember you don't have to be a programmer to contribute to an open source project. If you think you could contribute to the updating of the QGIS documentation please contact the team on the mailing list.

Interview with Nikolaus Batlogg about the large scale deployment of FOSSGIS in Vorarlberg, Austria

In 2011, the State of Vorarlberg, Austria became a new sponsor for the QGIS project. I was quite interested in the work they were doing as they are yet another great example of QGIS and FOSSGIS being used in an enterprise level setting. I arranged with Nikolaus Batlogg at the time to check in with... Read more »

New QGIS PDF and HTML manuals

A quick update from the QGIS documentation team today on the mailing list. The QGIS 1.8 manual is now available in HTML and PDF form.

HTML manual can be found at:
http://docs.qgis.org/html/en/docs/user_manual/index.html

PDF manual at:
http://docs.qgis.org/pdf/QGIS-1.8-UserGuide-en.pdf

This has been part of an ongoing effort from the documentation team since before the 1.8 release to bring our all our documentation into reStructedText rather then LaTeX. Moving to reStructedText allows quicker updates and a larger range of final output formats.

I would like to thank everyone who has been involved in this process as I know what a grueling process updating documentation can be.

Community notice

Just remember you don’t have to be a programmer to contribute to an open source project. If you think you could contribute to the updating of the QGIS documentation please contact the team on the mailing list.


Filed under: Open Source, qgis Tagged: FOSSGIS, gis, Open Source, osgeo, qgis, Quantum GIS

New QGIS PDF and HTML manuals

A quick update from the QGIS documentation team today on the mailing list. The QGIS 1.8 manual is now available in HTML and PDF form.

HTML manual can be found at: http://docs.qgis.org/html/en/docs/user_manual/index.html

PDF manual at: http://docs.qgis.org/pdf/QGIS-1.8-UserGuide-en.pdf

This has been part of an ongoing effort from the documentation team since before the 1.8 release to bring our all our documentation into reStructedText rather then LaTeX. Moving to reStructedText allows quicker updates and a larger range of final output formats.

I would like to thank everyone who has been involved in this process as I know what a grueling process updating documentation can be.

Community notice

Just remember you don't have to be a programmer to contribute to an open source project. If you think you could contribute to the updating of the QGIS documentation please contact the team on the mailing list.

New QGIS PDF and HTML manuals

  • Open Source
  • qgis tags:
  • FOSSGIS
  • gis
  • Open Source
  • osgeo
  • qgis
  • Quantum GIS

A quick update from the QGIS documentation team today on the mailing list. The QGIS 1.8 manual is now available in HTML and PDF form.

HTML manual can be found at: http://docs.qgis.org/html/en/docs/user_manual/index.html

PDF manual at: http://docs.qgis.org/pdf/QGIS-1.8-UserGuide-en.pdf

This has been part of an ongoing effort from the documentation team since before the 1.8 release to bring our all our documentation into reStructedText rather then LaTeX. Moving to reStructedText allows quicker updates and a larger range of final output formats.

I would like to thank everyone who has been involved in this process as I know what a grueling process updating documentation can be.

Community notice

Just remember you don't have to be a programmer to contribute to an open source project. If you think you could contribute to the updating of the QGIS documentation please contact the team on the mailing list.

New QGIS PDF and HTML manuals

  • Open Source
  • qgis tags:
  • FOSSGIS
  • gis
  • Open Source
  • osgeo
  • qgis
  • Quantum GIS

A quick update from the QGIS documentation team today on the mailing list. The QGIS 1.8 manual is now available in HTML and PDF form.

HTML manual can be found at: http://docs.qgis.org/html/en/docs/user_manual/index.html

PDF manual at: http://docs.qgis.org/pdf/QGIS-1.8-UserGuide-en.pdf

This has been part of an ongoing effort from the documentation team since before the 1.8 release to bring our all our documentation into reStructedText rather then LaTeX. Moving to reStructedText allows quicker updates and a larger range of final output formats.

I would like to thank everyone who has been involved in this process as I know what a grueling process updating documentation can be.

Community notice

Just remember you don't have to be a programmer to contribute to an open source project. If you think you could contribute to the updating of the QGIS documentation please contact the team on the mailing list.

Using a QGIS spatial index to speed up your code

If you need to do any kind of spatial operations in QGIS using Python or C++ you really want them to be as fast a possible in order reduce the amount of time you make the user wait. Lets take the simple scenario of a recent question that was asked on gis.stackexchange; Summing up values of neighboring polygons?.

I went for the SQL approach as I like how quick SQL can express what you need to do, however SQL is not the only way to skin a cat as spatialthoughts has shown in his blog post. Here Ujaval has used Python to find the neighboring polygons of each feature. Running the script on a small dataset yields results in reasonable time however running it on a larger dataset can take a long time.

In order to check if a feature touches another you need to have two features to compare against each other. The simple way to do this is to create two loops where you check each feature against every other feature. Here is a quick code example of just that.

layer = qgis.utils.iface.activeLayer()
# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def noindex():
    for feature in allfeatures.values():
        for f in allfeatures.values():
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

import timeit
print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

So the above code is pretty simple, just loop each feature and check against every other feature. No worries. No worries at least until you run this on a large dataset then I think you can see the issue here. Running the above code on a layer with around 28000 features takes 1912.41 seconds - that's 31 minutes. Holy crap!

Note: We put all the features of the layer into a dictionary as it will make lookup quicker in the later index example.

How can we speed up the above code? Lets take a gander at QgsSpatialIndex

QgsSpatialIndex to rule them all

QgsSpatialIndex is a wrapper around the open source SpatailIndex lib and uses a RTree for an index method. If you don't know what an index is you can think of it like the index in a book - a pointer to a location in the book rather then having to scan every page to find a word.

There isn't much to using QgsSpatialIndex just insert each QgsFeature and it handles the rest, when we need something out we just use the intersects method to return any features inside an area.

  layer = qgis.utils.iface.activeLayer()
  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def withindex():
      # Build the spatial index for faster lookup.
      index = QgsSpatialIndex()
      for f in allfeatures.values():
              index.insertFeature(f)

      # Loop each feature in the layer again and get only the features that are going to touch.
      for feature in allfeatures.values():
        # Get the ids of all the features in the index that are within
        # the bounding box of the current feature because these are the ones
        # that will be touching.
        ids = index.intersects(feature.geometry().boundingBox())
        for id in ids:
          f = allfeatures[id]
          if f == feature: continue
          touches = f.geometry().touches(feature.geometry())
          # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)

Running this code on our 28000 feature layer returns the results in 10 seconds. 31 minutes down to 10 seconds by just using a spatial index. Nice!

So the next time you need to do some spatial operations remember to use the handy QgsSpatialIndex in order to speed up your code. If you don't want to use QgsSpatialIndex, or need some more flexiblity, you could even use the Python RTree module.

Full code

  layer = qgis.utils.iface.activeLayer()

  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def noindex():
        for feature in allfeatures.values():
            for f in allfeatures.values():
                touches = f.geometry().touches(feature.geometry())
                # It doesn't matter if we don't return anything it's just an example

  def withindex():
        # Build the spatial index for faster lookup.
        index = QgsSpatialIndex()
        map(index.insertFeature, allfeatures.values())

        # Loop each feature in the layer again and get only the features that are going to touch.
        for feature in allfeatures.values():
          ids = index.intersects(feature.geometry().boundingBox())
          for id in ids:
            f = allfeatures[id]
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)
  print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

Simple operations with Sextante

Using a QGIS spatial index to speed up your code

If you need to do any kind of spatial operations in QGIS using Python or C++ you really want them to be as fast a possible in order reduce the amount of time you make the user wait. Lets take the simple scenario of a recent question that was asked on gis.stackexchange; Summing up values of neighboring polygons?.

I went for the SQL approach as I like how quick SQL can express what you need to do, however SQL is not the only way to skin a cat as spatialthoughts has shown in his blog post. Here Ujaval has used Python to find the neighboring polygons of each feature. Running the script on a small dataset yields results in reasonable time however running it on a larger dataset can take a long time.

In order to check if a feature touches another you need to have two features to compare against each other. The simple way to do this is to create two loops where you check each feature against every other feature. Here is a quick code example of just that.

layer = qgis.utils.iface.activeLayer()
# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def noindex():
        for feature in allfeatures.values():
                for f in allfeatures.values():
                        touches = f.geometry().touches(feature.geometry())
                        # It doesn't matter if we don't return anything it's just an example

import timeit
print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

So the above code is pretty simple, just loop each feature and check against every other feature. No worries. No worries at least until you run this on a large dataset then I think you can see the issue here. Running the above code on a layer with around 28000 features takes 1912.41 seconds – that’s 31 minutes. Holy crap!

Note: We put all the features of the layer into a dictionary as it will make lookup quicker in the later index example.

How can we speed up the above code? Lets take a gander at QgsSpatialIndex

QgsSpatialIndex to rule them all

QgsSpatialIndex is a wrapper around the open source SpatailIndex lib and uses a RTree for an index method. If you don’t know what an index is you can think of it like the index in a book – a pointer to a location in the book rather then having to scan every page to find a word.

There isn’t much to using QgsSpatialIndex just insert each QgsFeature and it handles the rest, when we need something out we just use the intersects method to return any features inside an area.

layer = qgis.utils.iface.activeLayer()
# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def withindex():
        # Build the spatial index for faster lookup.
        index = QgsSpatialIndex()
        for f in allfeatures.values():
                index.insertFeature(f)

        # Loop each feature in the layer again and get only the features that are going to touch.
        for feature in allfeatures.values():
          # Get the ids of all the features in the index that are within
          # the bounding box of the current feature because these are the ones
          # that will be touching.
          ids = index.intersects(feature.geometry().boundingBox())
          for id in ids:
            f = allfeatures[id]
            if f == feature: continue
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

import timeit
print "With Index: %s seconds " % timeit.timeit(withindex,number=1)

Running this code on our 28000 feature layer returns the results in 10 seconds. 31 minutes down to 10 seconds by just using a spatial index. Nice!

So the next time you need to do some spatial operations remember to use the handy QgsSpatialIndex in order to speed up your code. If you don’t want to use QgsSpatialIndex, or need some more flexiblity, you could even use the Python RTree module.

Full code

layer = qgis.utils.iface.activeLayer()

# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def noindex():
	for feature in allfeatures.values():
		for f in allfeatures.values():
			touches = f.geometry().touches(feature.geometry())
			# It doesn't matter if we don't return anything it's just an example

def withindex():
	# Build the spatial index for faster lookup.
	index = QgsSpatialIndex()
	map(index.insertFeature, allfeatures.values())

	# Loop each feature in the layer again and get only the features that are going to touch.
	for feature in allfeatures.values():
	  ids = index.intersects(feature.geometry().boundingBox())
	  for id in ids:
	    f = allfeatures[id]
	    touches = f.geometry().touches(feature.geometry())
	    # It doesn't matter if we don't return anything it's just an example

import timeit
print "With Index: %s seconds " % timeit.timeit(withindex,number=1)
print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)


Filed under: Open Source, qgis Tagged: FOSSGIS, gis, qgis, Quantum GIS, spatial operations

Using a QGIS spatial index to speed up your code

  • Open Source
  • qgis tags:
  • FOSSGIS
  • gis
  • qgis
  • Quantum GIS
  • spatial operations

If you need to do any kind of spatial operations in QGIS using Python or C++ you really want them to be as fast a possible in order reduce the amount of time you make the user wait. Lets take the simple scenario of a recent question that was asked on gis.stackexchange; Summing up values of neighboring polygons?.

I went for the SQL approach as I like how quick SQL can express what you need to do, however SQL is not the only way to skin a cat as spatialthoughts has shown in his blog post. Here Ujaval has used Python to find the neighboring polygons of each feature. Running the script on a small dataset yields results in reasonable time however running it on a larger dataset can take a long time.

In order to check if a feature touches another you need to have two features to compare against each other. The simple way to do this is to create two loops where you check each feature against every other feature. Here is a quick code example of just that.

layer = qgis.utils.iface.activeLayer()
# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def noindex():
    for feature in allfeatures.values():
        for f in allfeatures.values():
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

import timeit
print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

So the above code is pretty simple, just loop each feature and check against every other feature. No worries. No worries at least until you run this on a large dataset then I think you can see the issue here. Running the above code on a layer with around 28000 features takes 1912.41 seconds - that's 31 minutes. Holy crap!

Note: We put all the features of the layer into a dictionary as it will make lookup quicker in the later index example.

How can we speed up the above code? Lets take a gander at QgsSpatialIndex

QgsSpatialIndex to rule them all

QgsSpatialIndex is a wrapper around the open source SpatailIndex lib and uses a RTree for an index method. If you don't know what an index is you can think of it like the index in a book - a pointer to a location in the book rather then having to scan every page to find a word.

There isn't much to using QgsSpatialIndex just insert each QgsFeature and it handles the rest, when we need something out we just use the intersects method to return any features inside an area.

  layer = qgis.utils.iface.activeLayer()
  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def withindex():
      # Build the spatial index for faster lookup.
      index = QgsSpatialIndex()
      for f in allfeatures.values():
              index.insertFeature(f)

      # Loop each feature in the layer again and get only the features that are going to touch.
      for feature in allfeatures.values():
        # Get the ids of all the features in the index that are within
        # the bounding box of the current feature because these are the ones
        # that will be touching.
        ids = index.intersects(feature.geometry().boundingBox())
        for id in ids:
          f = allfeatures[id]
          if f == feature: continue
          touches = f.geometry().touches(feature.geometry())
          # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)

Running this code on our 28000 feature layer returns the results in 10 seconds. 31 minutes down to 10 seconds by just using a spatial index. Nice!

So the next time you need to do some spatial operations remember to use the handy QgsSpatialIndex in order to speed up your code. If you don't want to use QgsSpatialIndex, or need some more flexiblity, you could even use the Python RTree module.

Full code

  layer = qgis.utils.iface.activeLayer()

  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def noindex():
        for feature in allfeatures.values():
            for f in allfeatures.values():
                touches = f.geometry().touches(feature.geometry())
                # It doesn't matter if we don't return anything it's just an example

  def withindex():
        # Build the spatial index for faster lookup.
        index = QgsSpatialIndex()
        map(index.insertFeature, allfeatures.values())

        # Loop each feature in the layer again and get only the features that are going to touch.
        for feature in allfeatures.values():
          ids = index.intersects(feature.geometry().boundingBox())
          for id in ids:
            f = allfeatures[id]
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)
  print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

Using a QGIS spatial index to speed up your code

  • Open Source
  • qgis tags:
  • FOSSGIS
  • gis
  • qgis
  • Quantum GIS
  • spatial operations

If you need to do any kind of spatial operations in QGIS using Python or C++ you really want them to be as fast a possible in order reduce the amount of time you make the user wait. Lets take the simple scenario of a recent question that was asked on gis.stackexchange; Summing up values of neighboring polygons?.

I went for the SQL approach as I like how quick SQL can express what you need to do, however SQL is not the only way to skin a cat as spatialthoughts has shown in his blog post. Here Ujaval has used Python to find the neighboring polygons of each feature. Running the script on a small dataset yields results in reasonable time however running it on a larger dataset can take a long time.

In order to check if a feature touches another you need to have two features to compare against each other. The simple way to do this is to create two loops where you check each feature against every other feature. Here is a quick code example of just that.

layer = qgis.utils.iface.activeLayer()
# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def noindex():
    for feature in allfeatures.values():
        for f in allfeatures.values():
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

import timeit
print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

So the above code is pretty simple, just loop each feature and check against every other feature. No worries. No worries at least until you run this on a large dataset then I think you can see the issue here. Running the above code on a layer with around 28000 features takes 1912.41 seconds - that's 31 minutes. Holy crap!

Note: We put all the features of the layer into a dictionary as it will make lookup quicker in the later index example.

How can we speed up the above code? Lets take a gander at QgsSpatialIndex

QgsSpatialIndex to rule them all

QgsSpatialIndex is a wrapper around the open source SpatailIndex lib and uses a RTree for an index method. If you don't know what an index is you can think of it like the index in a book - a pointer to a location in the book rather then having to scan every page to find a word.

There isn't much to using QgsSpatialIndex just insert each QgsFeature and it handles the rest, when we need something out we just use the intersects method to return any features inside an area.

  layer = qgis.utils.iface.activeLayer()
  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def withindex():
      # Build the spatial index for faster lookup.
      index = QgsSpatialIndex()
      for f in allfeatures.values():
              index.insertFeature(f)

      # Loop each feature in the layer again and get only the features that are going to touch.
      for feature in allfeatures.values():
        # Get the ids of all the features in the index that are within
        # the bounding box of the current feature because these are the ones
        # that will be touching.
        ids = index.intersects(feature.geometry().boundingBox())
        for id in ids:
          f = allfeatures[id]
          if f == feature: continue
          touches = f.geometry().touches(feature.geometry())
          # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)

Running this code on our 28000 feature layer returns the results in 10 seconds. 31 minutes down to 10 seconds by just using a spatial index. Nice!

So the next time you need to do some spatial operations remember to use the handy QgsSpatialIndex in order to speed up your code. If you don't want to use QgsSpatialIndex, or need some more flexiblity, you could even use the Python RTree module.

Full code

  layer = qgis.utils.iface.activeLayer()

  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def noindex():
        for feature in allfeatures.values():
            for f in allfeatures.values():
                touches = f.geometry().touches(feature.geometry())
                # It doesn't matter if we don't return anything it's just an example

  def withindex():
        # Build the spatial index for faster lookup.
        index = QgsSpatialIndex()
        map(index.insertFeature, allfeatures.values())

        # Loop each feature in the layer again and get only the features that are going to touch.
        for feature in allfeatures.values():
          ids = index.intersects(feature.geometry().boundingBox())
          for id in ids:
            f = allfeatures[id]
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)
  print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

Using a QGIS spatial index to speed up your code

If you need to do any kind of spatial operations in QGIS using Python or C++ you really want them to be as fast a possible in order reduce the amount of time you make the user wait. Lets take the simple scenario of a recent question that was asked on gis.stackexchange; Summing up values of neighboring polygons?.

I went for the SQL approach as I like how quick SQL can express what you need to do, however SQL is not the only way to skin a cat as spatialthoughts has shown in his blog post. Here Ujaval has used Python to find the neighboring polygons of each feature. Running the script on a small dataset yields results in reasonable time however running it on a larger dataset can take a long time.

In order to check if a feature touches another you need to have two features to compare against each other. The simple way to do this is to create two loops where you check each feature against every other feature. Here is a quick code example of just that.

layer = qgis.utils.iface.activeLayer()
# Select all features along with their attributes
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
# Get all the features to start
allfeatures = {feature.id(): feature for (feature) in layer}

def noindex():
    for feature in allfeatures.values():
        for f in allfeatures.values():
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

import timeit
print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

So the above code is pretty simple, just loop each feature and check against every other feature. No worries. No worries at least until you run this on a large dataset then I think you can see the issue here. Running the above code on a layer with around 28000 features takes 1912.41 seconds - that's 31 minutes. Holy crap!

Note: We put all the features of the layer into a dictionary as it will make lookup quicker in the later index example.

How can we speed up the above code? Lets take a gander at QgsSpatialIndex

QgsSpatialIndex to rule them all

QgsSpatialIndex is a wrapper around the open source SpatailIndex lib and uses a RTree for an index method. If you don't know what an index is you can think of it like the index in a book - a pointer to a location in the book rather then having to scan every page to find a word.

There isn't much to using QgsSpatialIndex just insert each QgsFeature and it handles the rest, when we need something out we just use the intersects method to return any features inside an area.

layer = qgis.utils.iface.activeLayer()
  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def withindex():
      # Build the spatial index for faster lookup.
      index = QgsSpatialIndex()
      for f in allfeatures.values():
              index.insertFeature(f)

      # Loop each feature in the layer again and get only the features that are going to touch.
      for feature in allfeatures.values():
        # Get the ids of all the features in the index that are within
        # the bounding box of the current feature because these are the ones
        # that will be touching.
        ids = index.intersects(feature.geometry().boundingBox())
        for id in ids:
          f = allfeatures[id]
          if f == feature: continue
          touches = f.geometry().touches(feature.geometry())
          # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)

Running this code on our 28000 feature layer returns the results in 10 seconds. 31 minutes down to 10 seconds by just using a spatial index. Nice!

So the next time you need to do some spatial operations remember to use the handy QgsSpatialIndex in order to speed up your code. If you don't want to use QgsSpatialIndex, or need some more flexiblity, you could even use the Python RTree module.

Full code

layer = qgis.utils.iface.activeLayer()

  # Select all features along with their attributes
  allAttrs = layer.pendingAllAttributesList()
  layer.select(allAttrs)
  # Get all the features to start
  allfeatures = {feature.id(): feature for (feature) in layer}

  def noindex():
        for feature in allfeatures.values():
            for f in allfeatures.values():
                touches = f.geometry().touches(feature.geometry())
                # It doesn't matter if we don't return anything it's just an example

  def withindex():
        # Build the spatial index for faster lookup.
        index = QgsSpatialIndex()
        map(index.insertFeature, allfeatures.values())

        # Loop each feature in the layer again and get only the features that are going to touch.
        for feature in allfeatures.values():
          ids = index.intersects(feature.geometry().boundingBox())
          for id in ids:
            f = allfeatures[id]
            touches = f.geometry().touches(feature.geometry())
            # It doesn't matter if we don't return anything it's just an example

  import timeit
  print "With Index: %s seconds " % timeit.timeit(withindex,number=1)
  print "Without Index: %s seconds " % timeit.timeit(noindex,number=1)

Happy New Year

and thank you for a great 2012!

The view counter shows a staggering 250,000 views for last year. If that isn’t a reason to celebrate!

Here’s a quick recap with the top ten posts last year which were split between the two main topics pgRouting and QGIS:

  1. A Beginner’s Guide to pgRouting
  2. Table Joins – A New Feature in QGIS 1.7
  3. How to Specify Data Types of CSV Columns for Use in QGIS
  4. QGIS Server on Windows7 Step-by-step
  5. Osm2po Part 2 – PgRouting on OSM the Easy Way
  6. An osm2po Quickstart
  7. QGIS Server on Ubuntu Step-by-step
  8. Converting MXD to QGIS Project File
  9. Stamen Maps for QGIS
  10. Mapping Density with Hexagonal Grids

All the best for 2013!


New QGIS Symbol Packages

So far, QGIS does not come with many default symbols. Quite often one just needs two or three colors that go well together. That’s why I created a series of simple fill symbols based on ColorBrewer. They are available on Github QGIS-resources:

As always, these XMLs can be imported using Style Manager.

polysymbols

Another great addition to QGIS-resources was added this week by user aplannersguide. He shared his styles for osm2pgsql layers:

bdd73ba0-4ad3-11e2-8d74-1327374e522c


  • <<
  • Page 92 of 142 ( 2821 posts )
  • >>

Back to Top

Sustaining Members