' ************************************************************ ' Cut holes.ave ' This script is used for to fix shapefiles that have the holes ' listed as separate polygons, rather than cut out. ' It was written by Timothy S. Thomas. ' Editing began on 3/16/04, and was last edited on 3/16/04. ' It is based on "explode to new file" and "find neighbors". ' ************************************************************ theView = av.GetActiveDoc theFTheme = theView.GetActiveThemes.Get(0) theFTab = theFTheme.GetFTab numRecs = theFTab.GetNumRecords shapeField = theFTab.FindField("Shape") ' ********************************************************** ' Create a new shapefile to hold the new shapes ' ********************************************************** ' Shows message in message bar av.ShowMsg("Creating exploded file") ' Creates file FTabFN = theFTab.GetSrcName.GetFileName baseString = FTabFN.GetBaseName extString = FTabFN.GetExtension newString = FTabFN.AsString.Substitute(baseString,"") new2String = baseString.Substitute(extString,"shp") newFTabFN = FileDialog.Put( (newString + "cleaned " + new2String).AsFileName, "*.shp","Shapefile name") newFTab = FTab.MakeNew(newFTabFN,Polygon) ' ********************************************************** ' This allows the user to pick a field as the basic unit for ' evaluation ' ********************************************************** ' Gets new field list, reflecting deletions of fields fieldList = theFTab.GetFields.Clone idField = MsgBox.ChoiceAsString(fieldList,"Select unit ID field", "Choose ID field") ' ********************************************************** ' Establish unique polygon id ' ********************************************************** fieldList.Insert("") uniqidString = MsgBox.ChoiceAsString(fieldList,"Select Unique ID field", "Choose Unique ID field") if (uniqidString = "") then theFTab.SetEditable(True) isFld = theFTab.FindField("UniqID") if (isFld <> nil) then idnew = MsgBox.YesNo("UniqID is already a field. Do you want to use it?", "Use UniqID?",True) if (idnew) then uniqidField = isFld else newName = MsgBox.Input("Name of new ID","New name","NewID") uniqidField = Field.Make(newName,#FIELD_LONG,8,0) theFTab.AddFields({uniqidField}) for each rec in theFTab theFTab.SetValue(uniqidField,rec,rec+1) end end else uniqidField = Field.Make("UniqID",#FIELD_LONG,8,0) theFTab.AddFields({uniqidField}) for each rec in theFTab theFTab.SetValue(uniqidField,rec,rec+1) end end theFTab.SetEditable(False) else uniqidField = uniqidString end uniqidString = uniqidField.AsString ' ********************************************************** ' Clone fields for newFTab ' ********************************************************** newshapeField = newFTab.FindField("Shape") inFields = theFTab.GetFields newFields = List.Make for each f in inFields if (f.GetName <> "shape") then newFields.Add(f.Clone) end end newFTab.AddFields(newFields) ' ********************************************************** ' Selecting records one at a time and adding to newFTab ' ********************************************************** av.ShowStopButton av.ShowMsg("Cleaning polygons and cutting holes") for each recnum in 0..(numrecs-1) theShape = theFTab.ReturnValue(shapeField,recnum) theID = theFTab.ReturnValue(idField,recnum) theuniqID = theFTab.ReturnValue(uniqidField,recnum) theArea = theShape.ReturnArea theFTab.SelectByPolygon(theShape,#VTAB_SELTYPE_NEW) outCode = 1 outShape = theShape ' ********************************************************** ' Checks to see if polygon is contained. If so, it is ' skipped. If it contains other polys, then subtracts ' them. If neither, then simply output. ' ********************************************************** for each s in theFTab.GetSelection otherPoly = theFTab.ReturnValue(shapeField,s) otherID = theFTab.ReturnValue(idField,s) otheruniqID = theFTab.ReturnValue(uniqidField,s) otherArea = otherPoly.ReturnArea edgeCode = 0 if ((otheruniqID <> theuniqID) And (otherID = theID)) then area = theShape.ReturnIntersection(otherPoly).ReturnArea if (area.IsNull) then area = otherPoly.ReturnIntersection(theShape).ReturnArea end if (area.IsNull.Not) then if (theShape.Contains(otherPoly)) then outShape = outShape.ReturnDifference(otherPoly) edgeCode = 1 if (outCode = 1) then outCode = 2 elseif (outCode = 0) then outCode = 3 MsgBox.Info("This shape has and island within a lake within an island at" ++ theID.AsString,"IMPORTANT") end end if (otherPoly.Contains(theShape)) then edgeCode = 1 if (outCode = 1) then outCode = 0 elseif (outCode = 2) then outCode = 3 MsgBox.Info("This unit has and island within a lake within an island at" ++ theID.AsString,"IMPORTANT") end end if (edgeCode = 0) then if ((area > (0.95*theArea)) Or (area > (0.95*otherArea))) then MsgBox.Info("This unit has a probable boundary hole which ArcView could not find" ++ theID.AsString,"IMPORTANT") end end end end end if ((outCode = 1) Or (outCode = 2)) then rec = newFTab.AddRecord newFTab.SetValue(newshapeField,rec,outShape) for each fld in theFTab.GetFields fldName = fld.GetName if (fldName <> "shape") then newfld = newFTab.FindField(fldName) val = theFTab.ReturnValue(fld,recnum) newFTab.SetValue(newfld,rec,val) end end end av.SetStatus(100*(recnum+1)/numrecs) av.ShowMsg("Cleaning polygons and cutting holes"++recnum.AsString++"out of"++numrecs.AsString) end ' Clears message in message bar av.ClearMsg ' Turns off editing in the FTab newFTab.SetEditable(false) newFTheme = FTheme.Make ( newFTab ) theView.AddTheme ( newFTheme ) theFTheme.ClearSelection ' Removes garbage objects av.PurgeObjects