4

I need to calculate a metric for similarity of shapes (Hammond or Hausdorff) between polygons created from a vectorized map and official district polygons.

Now, I've done some searching and found this:

Polygon Shape Similarity using QGIS but it apparently applies to QGIS2, so I don't know how to get the script mentioned there into the toolbox of QGIS3.

It also seems like there is some built-in functionality for Hammond or Hausdorff similarity in QGIS itself, judging from this: https://github.com/qgis/QGIS/tree/master/resources/function_help/json . But I have no idea how to access this or make it run.

My capabilities to perform programming or developing tasks is very limited, I'd either have to run something within the software, by installing a plugin or copying files to a certain location, or maybe through running a python script from outside, but nothing more unless I have a clear guide, so advice like "You can run this [link] in PostGIS" might be good but not help me (sorry for that).

  • Unfortunately, adding a second GIS platform makes this two questions, in violation of the "One question per Question" policy. – Vince Sep 26 '19 at 15:15
  • Not really intuitive since the question is task specific and typically answers come in the form of "but you can do it in XY" anyway. It was just meant to widen the possible advice to my one question. But I'm not going to argue, it's a community thing apparently, so I just eliminated ArcGIS from the question. – Wernazuma Sep 26 '19 at 15:36
3

The QGIS Expression Builder has the hausdorff_distance function, which you can use to calculate the Hausdorff distance between two geometries. Here's an excerpt from the function description:

Returns the Hausdorff distance between two geometries. This is basically a measure of how similar or dissimilar 2 geometries are, with a lower distance indicating more similar geometries.

Syntax hausdorff_distance(geometry a,geometry b[,densify_fraction])

[ ] marks optional components

One way to use this function would be to use the Field Calculator to create a new field.

First, use the Field Calculator to add a new field, called "ID." Use this expression: @row_number.

Next, use the Field Calculator to add a field called "haus_dist_1." Use this expression:

hausdorff_distance($geometry, geometry(get_feature('layername', 'ID', "ID" +1)))

Explanation:

  • hausdorff_distance(geometry a, geometry b) measures the hausdorff distance between two geometries
  • $geometry is the geometry of the current feature
  • geometry(get_feature('layername', 'ID', "ID"+1)) is the geometry of the next feature down the attribute table (IE, the feature whose ID is one more than the ID of the current feature)
  • The entire expression calculates the hausdorff distance between the current feature and the next feature down in the attribute table. The feature with the highest ID will not have a hausdorff distance calculated, because there's no next feature, so the expression will be invalid for that feature.

Important: you must substitute the name of your layer where the function says 'layername'.

If you want the hausdorff distance between all the features in your layer, you'll need to repeat this step multiple times, creating multiple new fields. Simply adjust the "ID"+1 parameter to "ID"+2, then "ID"+3, and so on until you've created a field for every possible combination of features. Name them "haus_dist_2", "haus_dist_3", etc.


Update: You have two layers with a 1:1 relationship, and you want to compare each feature from the first layer to a single feature in the other layer. Use the same hausdorff_distance(geometry a, geometry b), but use different values for geometry a and geometry b. In this case, you only need to create one new field, because you're only making one set of comparisons.

The two layers must have a common field. I'll assume that the common field in the first layer is called "join_field_1", and the common field in the second layer is called "join_field_1". So if a feature in the first layer has "join_field_1" = 15, the corresponding feature in the second layer has "join_field_2" = 15.

Use this expression in the Field Calculator to add a new field to the first layer. Substitute the actual names of your join fields into the following expression. Also substitute the name of the second layer.

hausdorff_distance($geometry, geometry(get_feature('secondlayer', 'join_field_2', "join_field_1")))
  • great, thanks a lot for the explanation, I think I can get that to work. However, the compared features are in two distinct layers, they share a common ID field and have a strict 1:1 relation. The compared geometries will ultimately go into the thousands, so adding new fields is prohibitive. – Wernazuma Sep 26 '19 at 17:19
  • Oh, I see. I assumed you wanted to compare all the features in a single layer. Your actual setup is much more reasonable. I'll update my answer with a solution. – csk Sep 26 '19 at 17:57
  • Thank you! Works like a charm! And thank you also for the comprehensive explanation, this makes doing it very easy. Cheers – Wernazuma Sep 27 '19 at 12:58

Your Answer

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

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