0

I have a KMZ file of north-eastern Thailand which marks the boundaries of a larger district and it's sub-districts. Still new to GIS and in the process of getting familiar with QGIS, I wonder can anyone advise me how can I "extract" the boundaries of each of these sub-districts from that KMZ?

E.g. are there any QGIS plugins which could be used for this task?

5
  • Can you maybe include a screenshot to show what you mean? Is it that there is a single large boundary with lots of smaller boundaries within it and you want to get rid of the large one? – jonnyhuck Jul 2 '14 at 12:46
  • thanks, @jonnyhuck, the file is file is actually kmz, not kml,and it is published and downloadable by everyone on the internet, so I have no problems to share the file, assuming it helps to suggest an answer to my question: link – user1402897 Jul 2 '14 at 16:32
  • OK, so what exactly do you mean by "extract"? What do you want to end up with? – jonnyhuck Jul 3 '14 at 8:55
  • the linked file is a KMZ file of north-eastern Thailand which includes a number of districts inside it. As an analogy, think of the file would be the KMZ of the United States with all the boundaries of it's 50 states inside that "complete US KMZ". Following this this analogy, I would need to end up with a number of KML files: one KML outlining the USA as a whole, and further 50 files, each outlining the boundaries of each of the US states. Would be great if I could get some bullet points how to do that as I have more files of other areas of Thailand for which I to repeat the same. – user1402897 Jul 3 '14 at 13:40
  • See below for the first part. Before going on with the scripting - are you sure that you need them in 50 separate files? Do you know you can turn them on and off individually in Google Earth? This would be much more efficient way of working with the data if it suits your needs? – jonnyhuck Jul 3 '14 at 16:25
0

OK, so step 1 (getting the outline of all of them) is nice and easy. All you need is to go in QGIS to

Vector->Geoprocessing Tools->Dissolve

Which will open the dialog for the "Dissolve" tool.

Set your layer as the "Input Vector Layer", select a "Dissolve Field" that is the same for all of the features in the layer (I chose "tesellate"), create a location for the output shapefile, and tick "add result to canvas" like this...

enter image description here

Press "OK" and it will dissolve all of your features into one big one:

enter image description here

Close the dissolve tool.

Next, simply convert it to a KML/KMZ by right clicking on it in the "Layers" list (normally on the left of the screen), click "Save As", and set the format to "KML".

Done!

I'm afraid that splitting each feature to separate KML layers is a little more complex, and will require some scripting...

I recommend downloading the "Script Runner" plugin, and then run this code:

"""
    Explode a Shapefile CAD-style - each feature will become a new file.
"""

from qgis.core import *
import qgis.utils

class VectorExploder:
     def __init__(self, iface):

        #self.iface = iface

        # Load the layer
        inPath = "[PATH TO YOUR DATA]/NE_admin.kmz"
        outDirectory = "[OUTPUT DIRECTORY PATH]/"
        print inPath
        layer = QgsVectorLayer(inPath, "NE_admin", "ogr")
        if not layer.isValid():
            print "Layer failed to load!"
            return

        # Get the index of the 'Name' attribute
        idx = layer.fieldNameIndex('Name')

        # Loop through all of the features, saving each to file
        iter = layer.getFeatures()
        for feature in iter:

            #get the field list
            fields = feature.fields()
            featureName = feature.attributes()[idx]
            fileName = featureName.encode('utf8', 'replace')

            # create an instance of vector file writer, which will create the vector file.
            outPath = outDirectory + fileName + ".kml"
            #outPath = outDirectory + str(feature.id()) + ".kml"
            print outPath
            crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId)
            writer = QgsVectorFileWriter(outPath, "CP1250", fields, QGis.WKBPoint, crs, "KML")
            if writer.hasError() != QgsVectorFileWriter.NoError:
              print "Error when creating shapefile: ", writer.hasError()
              return

            # Load the feature into the writer
            writer.addFeature(feature)

            # delete the writer to flush features to disk (optional)
            del writer

def run_script(iface):
        exp = VectorExploder(qgis.utils.iface)

All you need to do first is add in your input file (instead of "[PATH TO YOUR DATA]") path and output directory (instead of "[OUTPUT DIRECTORY PATH]"), then save the file as a Python (.py) file somewhere. Then open the Script Runner plugin, load in the file (by pressing the "+" button) and press "Run Script".

This will separate every feature in your dataset (>2678 of them!) into a separate KML file. They will all be numbered, as my computer can't handle the encoding of the names, but I've left the code in there if you want to use names instead. Just swap the # from the line that starts "outfile" to the line below (also starting "outfile").

You can run this again and again for each of your datasets.

How's that?

7
  • Well... so far so GOOD... ;) The "easy bit" is done... (the outline file for NE that is, kept my MacBook busy for 20 min to create the outline...). Next I will go and try the extract the sub-districts with your script and ScriptRunner... I tell you, I am holding my breath as that would be too nice to be true if it works... Will surely report back. Thanks a MILLION ! – user1402897 Jul 4 '14 at 15:22
  • man, @jonnyhuck, you are an ABSOLUTE hero... worked like a charm and I can't express my gratitude enough. Absolutely brilliant advice... !!! I just have to run a script now which passes all the 2678 outlines to GoogleMaps to return the "province" (so that I don't have to manually scour through all the KMLs and don't have to manually (re)name them, but that's a piece of cake...). And then I am done... "How is that" you asked: SHEER BRILLIANCE :) :) :) THANKS A MILLION !! – user1402897 Jul 4 '14 at 15:42
  • Great! No problem, I'm really glad it worked for you :). As I say, If you swap that line in the code it will call the files by name instead of the number, I just couldn't run that on my laptop as it can't handle the string encoding. If you could click to accept the answer I'd really appreciate it! Thanks!! – jonnyhuck Jul 4 '14 at 16:21
  • Thanks, @jonnyhuck, I can't get the names either. I assume it's the same issue which you indicated by saying "my computer can't handle names" and basically is an ascii/unicode encoding issue while trying to output the Thai (non-ascii) characters. I am not a developer but googled a bit and found this link below which, as it looks to me, might help to get the Python script to output correctly. Would you mind to check and let me know if that can be fixed by adjusting your script accordingly? See "Frustractions 3" section in this link - pythonhosted.org/kitchen/unicode-frustrations.html – user1402897 Jul 5 '14 at 2:54
  • extending on the above: when I run your script when trying to output the "names" instead of the index number then I get the error below (I assume you got the same when you said "my computer cant't handle...")? – user1402897 Jul 5 '14 at 2:59
0

Use the split vector layers tool, which

Creates a set of vectors in an output folder based on an input layer and an attribute. The output folder will contain as many layers as the unique values found in the desired field.

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.