Deleting polygons smaller than certain dimension using ArcGIS Desktop?

Use my script from Checking if polygon fits inside another polygon using ArcGIS or QGIS?

to create points inside your polygons. Each point is a centre of maximum inscribed circle of the parcel. Please note, script tested on shapefiles only and it does not handle polygons with holes, i.e. donut like polygons.

Table of centre point contains field theDist, that is the radius of above circle. enter image description here

Select all points with theDist=>20, and create 20m buffers around them: enter image description here Use Minimum Bounding Geometry to create rectangles from buffers enter image description here Attach this script to tool with no parameters. It is a tool to run from mxd

import arcpy, traceback, os, sys,math
from math import radians,sin,cos

mxd = arcpy.mapping.MapDocument("CURRENT")
parent=arcpy.mapping.ListLayers(mxd,"parent")[0]
child=arcpy.mapping.ListLayers(mxd,"child")[0]

# NUMERIC ! common field
linkField="PAR_ID"
d=arcpy.Describe(parent)
SR=d.spatialReference
g=arcpy.Geometry()
gr=(math.sqrt(5)-1)/2

try:
    def showPyMessage():
        arcpy.AddMessage(str(time.ctime()) + " - " + message)

    #golden section to find minimum
    def gss(a,b,tol):
        c=b-gr*(b-a)
        d=a+gr*(b-a)
        while abs(c-d)>tol:       
            fc=f(c);fd=f(d)
            if fc<fd:
                b=d
                d=c
                c=b-gr*(b-a)
            else:
                a=c
                c=d
                d=a+gr*(b-a)
        return (b+a)/2

    # rotate polygon
    def ShapeMake(pGon,angle):
        ar=arcpy.Array()
        a=radians(angle)
        part=pGon.getPart(0)
        for p in part:
            x,y=p.X-pGon.centroid.X,p.Y-pGon.centroid.Y
            xN=cos(a)*x+sin(a)*y
            yN=-sin(a)*x+cos(a)*y
            pN=arcpy.Point(xN+pGon.centroid.X,yN+pGon.centroid.Y)
            ar.add(pN)
        pgonRotated=arcpy.Polygon(ar,SR)
        return pgonRotated

    #function to minimise
    def f(a):
        pgonRot=ShapeMake(square,a)
        intR=pgonRot.difference(bigPolygon)
        return intR.area

    result=arcpy.GetCount_management(child)
    nF=int(result.getOutput(0))
    initFidList=[]
    arcpy.SetProgressor("step", "", 0, nF,1)
    with arcpy.da.UpdateCursor(child, ("SHAPE@",linkField)) as rows:
        for row in rows:
            square=row[0]
            PID=row[1]
            quer='%s%s%s=%i'%('"',linkField,'"',PID)
            parent.definitionQuery=quer
            bigPolygon=arcpy.CopyFeatures_management(parent,g)[0]
            intR=square.difference(bigPolygon)

            # square fits inside parent without rotation
            if intR.area==0:initFidList.append(PID)
            # find minimum area outside parent at differenr rotations
            else:
                angle=gss(0.0,90,1e-3)
                # square fits if rotated
                if f(angle)==0:
                    row[0]=ShapeMake(square,angle)
                    rows.updateRow(row)
                    initFidList.append(PID)
            arcpy.SetProgressorPosition()

    quer='"FID" IN '+str(initFidList)
    quer='%s%s%s in %s'%('"',linkField,'"',str(tuple(initFidList)))
    parent.definitionQuery=""
    arcpy.SelectLayerByAttribute_management(child, "NEW_SELECTION", quer)


except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

Script works on shapefiles and assumes:

  1. that your original polygons named PARENT
  2. that your squares polygons named CHILD
  3. They have common numeric field "PAR_ID"

It child fits completely into original, script adds this square to selection. If not it attempts to fit it by rotating around centre points, and adds to selection if successful

enter image description here


Interesting question!

OK thinking out aloud here and untested so may not capture all possible shapes. It looks like you are mapping to a cell size of 10m and that your rectangular polygons are raster based. The logic I am suggesting only works if the original raster based polygons do not touch each other. In @FelixIP answer he has polygons sharing boundaries. If this is truly the case how about this approach?

  1. Convert your polygons to a binary grid where a cell covered by your polygon becomes 1, everything else a 0.
  2. Run the Focal Statistics tool with a circular window of 2 pixels with SUM as the option.
  3. Any pixel surrounded by 4x4 1's will sum up to 16.
  4. You could then convert only pixels that are 16 into points and use those to select the polygons as the required minimum dimension. You just need to invert the selection to find the ones you don't want.