In my area, PINs (Parcel Id Numbers) are 10-digit numbers built from the coordinate of the centroid of the parcel (polygon). I have no coding experience, but I know what I need is fairly straightforward and hope someone can help me.

Note- the 10-digit PIN is NOT a coordinate, it is an encoded coordinate and the actual coordinate would need to parsed out.

What I wish to do is create an input field labeled 'PIN Search' where a user can input a 10-digit PIN and after hitting enter the program would determine the coordinate and, ideally, select the nearest polygon at that coordinate and zoom/pan to its extent. I would be happy if it would just zoom/pan to the coordinate at some predetermined scale.

I suppose I need to learn to write some python code. I have no idea how to create an input field, I know what to do with the data to generate a coordinate, but then I would like to select the nearest polygon to that location and pan/zoom to its extent. I would be happy to just pan/zoom to the coordinate, though.

Is this something I would need to create a plugin for or can it be done in some sort of macro?

EDIT --How a PIN becomes a coordinate CRS = NAD83 / North Carolina (ftUS) EPSG = 2264

extents: xmin = 400000, ymin = 400000, xmax = 1300000, ymax = 1300000

PIN is 10-digit number of the form x1 y1 x2 y2 x3 y3 x4 y4 x5 y5 The coordinate is derived as X=x1 x2 x3 x4 x5 x6, Y=y1 y2 y3 y4 y5 y6 where x6 and y6 are = 0 and if x1 = 0,1,2,or 3 then 10 is added and if y1 = 0,1,2,3 then 10 is added. Examples: PIN = 9876543210 generates coordinate x=975310, y=864200: PIN = 0123456789 generates coordinate x= 1024680, y= 1135790

  • Could you please provide an example of a PIN and how it becomes a coordinate? In which Coordinate System Reference are your data?
    – mgri
    Commented Jan 13, 2017 at 9:37

1 Answer 1


This was solved by creating a Plug In with the following code.

    def run(self):
    """Run method that performs all the real work"""
    # show the dialog
    # Run the dialog event loop
    result = self.dlg.exec_()
    # See if OK was pressed
    if result:
        # get the PIN from the dialog box
        pin =self.dlg.PINvalue.text()
        scale = 1000
        if len(pin)<10:
            QMessageBox.information(self.iface.mainWindow(),"Error","Not a valid input")
        #compute coordinates
        x1 = pin[0]
        y1 = pin[1]
        if int(x1) < 5:
            x1 = '1' + x1
        if int(y1) < 5:
            y1 = '1' + y1
        Coordx = x1 + pin[2] + pin[4] + pin[6] + pin[8] + '0'
        Coordy = y1 + pin[3] + pin[5] + pin[7] + pin[9] + '0'      
        # create a rectangle to sort features by. Qgis will find overlapping features
        # it's ok that xmin & xmax are the same and ymin & ymax are the same.
        filterRect = QgsRectangle(
        projectRoot = QgsProject.instance().layerTreeRoot()
        parcelGroup = projectRoot.findGroup("Parcels") # replace with actual group name

        featFound = False

        for lyr in parcelGroup.findLayers():
                # get feature iterator and select first one that overlaps
                featFound = lyr.layer().getFeatures(QgsFeatureRequest(filterRect)).next()

            except StopIteration:
                # if none do just move on

        if featFound: # will still be false if no feature was found
            mapExtentRect = featFound.geometry().boundingBox()
            mapExtentRect = QgsRectangle(
                float(Coordx) - scale,
                float(Coordy) - scale, 
                float(Coordx) + scale,
                float(Coordy) + scale)
        # Set the extent to our new rectangle
        # Refresh the map

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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